loading
Generated 2025-06-23T17:35:06-04:00

All Files ( 67.77% covered at 3.75 hits/line )

257 files in total.
11957 relevant lines, 8103 lines covered and 3854 lines missed. ( 67.77% )
File % covered Lines Relevant Lines Lines covered Lines missed Avg. Hits / Line
app/actors/hyrax/actors/abstract_event_actor.rb 66.67 % 34 9 6 3 0.67
app/actors/hyrax/actors/after_optimistic_lock_validator.rb 53.85 % 40 13 7 6 0.54
app/actors/hyrax/actors/apply_order_actor.rb 23.81 % 70 42 10 32 0.24
app/actors/hyrax/actors/attach_members_actor.rb 25.58 % 99 43 11 32 0.26
app/actors/hyrax/actors/before_add_to_work_actor.rb 29.41 % 65 34 10 24 0.29
app/actors/hyrax/actors/before_attach_members_actor.rb 31.03 % 74 29 9 20 0.31
app/actors/hyrax/actors/before_model_actor.rb 53.85 % 45 13 7 6 0.54
app/actors/hyrax/actors/create_with_files_actor.rb 35.71 % 61 28 10 18 0.36
app/actors/hyrax/actors/data_set_actor.rb 80.00 % 17 5 4 1 0.80
app/actors/hyrax/actors/dissertation_actor.rb 100.00 % 8 3 3 0 1.00
app/actors/hyrax/actors/generic_work_actor.rb 100.00 % 8 3 3 0 1.00
app/actors/hyrax/actors/interpret_visibility_actor.rb 50.00 % 47 12 6 6 0.50
app/actors/hyrax/actors/optimistic_lock_validator.rb 64.29 % 37 14 9 5 0.64
app/controllers/application_controller.rb 68.57 % 109 35 24 11 2.11
app/controllers/catalog_controller.rb 100.00 % 437 164 164 0 1.02
app/controllers/concerns/deepblue/works_controller_behavior.rb 41.18 % 34 17 7 10 0.41
app/controllers/concerns/hyrax/breadcrumbs.rb 33.33 % 56 27 9 18 0.33
app/controllers/concerns/hyrax/collections_controller_behavior.rb 48.39 % 153 62 30 32 0.48
app/controllers/concerns/hyrax/works_controller_behavior.rb 30.00 % 96 30 9 21 0.30
app/controllers/deepblue/collections_controller_behavior.rb 37.50 % 95 32 12 20 0.38
app/controllers/deepblue/controller_workflow_event_behavior.rb 50.00 % 54 16 8 8 0.50
app/controllers/guest_user_message_controller.rb 100.00 % 16 6 6 0 1.00
app/controllers/hyrax/collections_controller.rb 47.89 % 170 71 34 37 0.48
app/controllers/hyrax/dashboard/collections_controller.rb 100.00 % 120 45 45 0 1.31
app/controllers/hyrax/data_sets_controller.rb 30.74 % 541 257 79 178 0.31
app/controllers/hyrax/deepblue_controller.rb 100.00 % 41 16 16 0 1.00
app/controllers/hyrax/dissertations_controller.rb 100.00 % 14 5 5 0 1.00
app/controllers/hyrax/file_sets_controller.rb 55.17 % 151 58 32 26 0.55
app/controllers/hyrax/generic_works_controller.rb 100.00 % 14 6 6 0 1.00
app/controllers/hyrax/my/collections_controller.rb 48.00 % 188 75 36 39 0.48
app/controllers/robots_controller.rb 92.31 % 43 26 24 2 1.81
app/forms/deepbluedocs/default_work_form_behavior.rb 76.32 % 177 38 29 9 0.76
app/forms/deepbluedocs/dissertation_work_form_behavior.rb 73.91 % 69 23 17 6 0.74
app/forms/deepbluedocs/generic_work_form_behavior.rb 75.00 % 71 24 18 6 0.75
app/forms/hyrax/data_set_form.rb 100.00 % 83 12 12 0 1.08
app/forms/hyrax/deepblue_form.rb 66.67 % 23 9 6 3 0.67
app/forms/hyrax/dissertation_form.rb 100.00 % 11 5 5 0 1.00
app/forms/hyrax/forms/collection_form.rb 55.22 % 182 67 37 30 0.55
app/forms/hyrax/generic_work_form.rb 100.00 % 11 5 5 0 1.00
app/helpers/application_helper.rb 100.00 % 2 1 1 0 1.00
app/helpers/deepblue/email_helper.rb 29.31 % 118 58 17 41 0.29
app/helpers/deepblue/event_helper.rb 80.00 % 61 25 20 5 0.96
app/helpers/deepblue/export_files_helper.rb 12.00 % 86 50 6 44 0.12
app/helpers/deepblue/ingest_helper.rb 13.27 % 355 113 15 98 0.13
app/helpers/deepblue/jira_helper.rb 22.77 % 330 101 23 78 0.23
app/helpers/deepblue/json_logger_helper.rb 79.26 % 250 135 107 28 11.31
app/helpers/deepblue/logging_helper.rb 72.22 % 151 72 52 20 9.49
app/helpers/deepblue/metadata_helper.rb 19.25 % 1039 504 97 407 27.04
app/helpers/deepblue/ordered_string_helper.rb 90.91 % 38 11 10 1 143.82
app/helpers/deepblue/provenance_helper.rb 92.86 % 46 14 13 1 2.14
app/helpers/deepblue/scheduler_helper.rb 60.00 % 47 15 9 6 0.60
app/helpers/deepblue/upload_helper.rb 54.55 % 60 22 12 10 0.55
app/helpers/deepblue_helper.rb 10.42 % 68 48 5 43 0.10
app/helpers/hyrax/ability_helper.rb 30.43 % 51 23 7 16 0.30
app/helpers/hyrax/branding_helper.rb 22.03 % 104 59 13 46 0.22
app/helpers/hyrax/embargo_helper.rb 19.19 % 215 99 19 80 0.23
app/helpers/hyrax_helper.rb 45.83 % 71 24 11 13 0.54
app/helpers/job_helper.rb 33.33 % 15 6 2 4 0.33
app/helpers/msg_helper.rb 58.82 % 42 17 10 7 0.59
app/indexers/data_set_indexer.rb 26.67 % 58 15 4 11 0.27
app/indexers/dissertation_indexer.rb 100.00 % 18 3 3 0 1.00
app/indexers/generic_work_indexer.rb 100.00 % 18 3 3 0 1.00
app/indexers/hyrax/collection_with_basic_metadata_indexer.rb 66.67 % 14 6 4 2 0.67
app/indexers/hyrax/file_set_indexer.rb 21.43 % 65 42 9 33 0.21
app/jobs/about_to_expire_embargoes_job.rb 87.50 % 44 24 21 3 1.63
app/jobs/globus_copy_job.rb 13.46 % 167 104 14 90 0.13
app/jobs/globus_job.rb 54.17 % 357 216 117 99 0.97
app/jobs/globus_restart_all_job.rb 98.18 % 85 55 54 1 2.84
app/jobs/hyrax/application_job.rb 100.00 % 9 2 2 0 1.00
app/mailers/application_mailer.rb 100.00 % 6 3 3 0 1.00
app/mailers/deepblue_mailer.rb 100.00 % 12 5 5 0 1.00
app/models/ability.rb 93.33 % 68 30 28 2 20.27
app/models/application_record.rb 100.00 % 3 2 2 0 1.00
app/models/collection.rb 41.62 % 413 197 82 115 3.12
app/models/concerns/deepblue/abstract_event_behavior.rb 100.00 % 89 44 44 0 1.45
app/models/concerns/deepblue/default_metadata.rb 100.00 % 745 298 298 0 5.97
app/models/concerns/deepblue/doi_behavior.rb 38.46 % 65 26 10 16 0.38
app/models/concerns/deepblue/email_behavior.rb 31.01 % 345 129 40 89 0.31
app/models/concerns/deepblue/embargoable_behavior.rb 32.56 % 100 43 14 29 0.37
app/models/concerns/deepblue/file_set_behavior.rb 32.84 % 155 67 22 45 0.63
app/models/concerns/deepblue/file_set_metadata.rb 100.00 % 57 28 28 0 1.54
app/models/concerns/deepblue/metadata_behavior.rb 55.32 % 201 94 52 42 1.26
app/models/concerns/deepblue/provenance_behavior.rb 49.06 % 784 265 130 135 1.77
app/models/concerns/deepblue/workflow_event_behavior.rb 31.25 % 115 32 10 22 0.31
app/models/concerns/hyrax/collection_behavior.rb 58.82 % 53 17 10 7 2.94
app/models/concerns/hyrax/uploaded_file.rb 100.00 % 16 8 8 0 1.00
app/models/concerns/umrdr/solr_document_behavior.rb 48.44 % 149 64 31 33 0.48
app/models/concerns/umrdr/umrdr_work_behavior.rb 40.00 % 96 45 18 27 0.40
app/models/concerns/umrdr/umrdr_work_metadata.rb 100.00 % 139 78 78 0 3.18
app/models/data_set.rb 64.52 % 490 217 140 77 43.35
app/models/dissertation.rb 100.00 % 15 5 5 0 1.00
app/models/file_set.rb 34.78 % 302 138 48 90 0.78
app/models/generic_work.rb 100.00 % 15 5 5 0 1.00
app/models/qa/local_authority.rb 100.00 % 2 1 1 0 1.00
app/models/qa/local_authority_entry.rb 100.00 % 3 2 2 0 1.00
app/models/search_builder.rb 100.00 % 16 4 4 0 1.00
app/models/solr_document.rb 52.58 % 335 97 51 46 1.45
app/models/user.rb 63.64 % 50 22 14 8 0.64
app/presenters/concerns/datacore/presents_archive_file.rb 45.83 % 48 24 11 13 0.46
app/presenters/guest_user_message_presenter.rb 100.00 % 11 4 4 0 1.00
app/presenters/hyrax/characterization_behavior.rb 45.76 % 167 59 27 32 0.46
app/presenters/hyrax/collection_presenter.rb 46.81 % 204 94 44 50 0.47
app/presenters/hyrax/data_set_presenter.rb 35.82 % 223 67 24 43 0.36
app/presenters/hyrax/deepblue_presenter.rb 64.29 % 41 14 9 5 0.64
app/presenters/hyrax/dissertation_presenter.rb 100.00 % 6 2 2 0 1.00
app/presenters/hyrax/ds_file_set_presenter.rb 38.24 % 88 34 13 21 0.38
app/presenters/hyrax/generic_work_presenter.rb 100.00 % 10 3 3 0 1.00
app/presenters/hyrax/work_show_presenter.rb 76.47 % 34 17 13 4 0.76
app/services/dataset/date_coverage_service.rb 96.15 % 119 52 50 2 4.06
app/services/deepblue/about_to_expire_embargoes_service.rb 100.00 % 86 41 41 0 4.10
app/services/deepblue/deactivate_expired_embargoes_service.rb 100.00 % 60 25 25 0 2.88
app/services/deepblue/doi_minting_service.rb 72.06 % 119 68 49 19 1.93
app/services/deepblue/log_exporter.rb 79.07 % 83 43 34 9 1.58
app/services/deepblue/log_extracter.rb 42.86 % 31 14 6 8 0.43
app/services/deepblue/log_filter.rb 42.31 % 429 208 88 120 0.54
app/services/deepblue/log_reader.rb 76.86 % 207 121 93 28 12.68
app/services/deepblue/log_reporter.rb 65.12 % 72 43 28 15 0.93
app/services/deepblue/logging_callback.rb 100.00 % 42 27 27 0 2.63
app/services/deepblue/logging_service.rb 53.85 % 26 13 7 6 2.08
app/services/deepblue/provenance_log_service.rb 21.21 % 111 66 14 52 0.21
app/services/deepblue/provenance_path.rb 56.52 % 68 23 13 10 0.57
app/services/deepblue/virus_scan_service.rb 100.00 % 34 18 18 0 1.22
app/services/deepblue/yaml_populate_service.rb 75.49 % 663 408 308 100 2.58
app/services/hyrax/collections/collection_member_service.rb 51.61 % 101 31 16 15 0.52
app/services/hyrax/embargo_service.rb 33.33 % 83 33 11 22 0.33
app/validators/hydra/future_date_validator.rb 25.00 % 32 12 3 9 0.25
config/application.rb 98.29 % 215 117 115 2 0.98
config/boot.rb 100.00 % 3 2 2 0 1.00
config/environment.rb 100.00 % 9 4 4 0 1.00
config/environments/test.rb 100.00 % 49 15 15 0 1.00
config/features.rb 100.00 % 14 4 4 0 1.00
config/initializers/application_controller_renderer.rb 100.00 % 6 0 0 0 0.00
config/initializers/assets.rb 100.00 % 11 1 1 0 1.00
config/initializers/backtrace_silencers.rb 100.00 % 7 0 0 0 0.00
config/initializers/bulkrax.rb 100.00 % 97 3 3 0 1.00
config/initializers/clamav.rb 57.14 % 13 7 4 3 0.57
config/initializers/config.rb 14.29 % 11 7 1 6 0.14
config/initializers/cookies_serializer.rb 100.00 % 5 1 1 0 1.00
config/initializers/devise.rb 100.00 % 295 17 17 0 1.00
config/initializers/event_logging.rb 100.00 % 18 2 2 0 6.00
config/initializers/ezid.rb 100.00 % 10 7 7 0 1.00
config/initializers/filter_parameter_logging.rb 100.00 % 4 1 1 0 1.00
config/initializers/hydra_config.rb 100.00 % 24 3 3 0 1.00
config/initializers/hyrax.rb 78.57 % 347 42 33 9 0.79
config/initializers/hyrax_callbacks.rb 100.00 % 52 0 0 0 0.00
config/initializers/inflections.rb 100.00 % 16 0 0 0 0.00
config/initializers/ldap_groups_lookup.rb 100.00 % 18 1 1 0 1.00
config/initializers/mailboxer.rb 100.00 % 22 10 10 0 1.00
config/initializers/mime_types.rb 100.00 % 8 4 4 0 1.00
config/initializers/mini_magick.rb 100.00 % 5 3 3 0 1.00
config/initializers/new_framework_defaults.rb 100.00 % 24 5 5 0 1.00
config/initializers/okcomputer.rb 100.00 % 5 2 2 0 1.00
config/initializers/provenance_logging.rb 100.00 % 10 1 1 0 1.00
config/initializers/rack_attack.rb 57.14 % 15 7 4 3 0.57
config/initializers/redis_config.rb 100.00 % 2 2 2 0 1.00
config/initializers/resque_config.rb 100.00 % 8 4 4 0 1.00
config/initializers/riiif.rb 50.00 % 26 14 7 7 0.50
config/initializers/session_store.rb 100.00 % 3 1 1 0 1.00
config/initializers/simple_form.rb 100.00 % 170 20 20 0 1.00
config/initializers/simple_form_bootstrap.rb 100.00 % 150 97 97 0 1.00
config/initializers/wrap_parameters.rb 100.00 % 14 2 2 0 1.50
config/routes.rb 93.98 % 160 83 78 5 0.94
config/spring.rb 100.00 % 6 2 2 0 2.50
lib/abstract_virus_scanner.rb 46.15 % 25 13 6 7 0.85
lib/active_fedora/persistence.rb 35.71 % 293 126 45 81 4.88
lib/devise/behaviors/http_header_authenticatable_behavior.rb 62.50 % 24 8 5 3 0.63
lib/devise/models/http_header_authenticatable.rb 100.00 % 17 7 7 0 1.00
lib/devise/strategies/http_header_authenticatable.rb 41.18 % 33 17 7 10 0.41
lib/email_logger.rb 83.33 % 14 6 5 1 0.83
lib/extensions/active_fedora/file/escaping_obsoletions.rb 62.50 % 14 8 5 3 0.63
lib/extensions/extensions.rb 100.00 % 21 8 8 0 1.00
lib/extensions/hydra/access_controls/permission/escaping_obsoletions.rb 100.00 % 19 9 9 0 16.44
lib/extensions/hyrax/admin_stats_presenter/admin_stats_presenter_behavior.rb 100.00 % 23 12 12 0 1.92
lib/extensions/hyrax/collapsable_section_presenter/collapsable_section_presenter_behavior.rb 100.00 % 23 8 8 0 1.25
lib/extensions/hyrax/collections_controller/render_bookmarks_control.rb 100.00 % 14 7 7 0 1.14
lib/extensions/hyrax/downloads_controller/variable_download_sourcing.rb 45.45 % 29 11 5 6 0.45
lib/extensions/qa/authorities/collections/collections_search.rb 37.50 % 26 16 6 10 0.38
lib/hydra/works/models/concerns/file_set/mime_types.rb 58.33 % 58 24 14 10 0.58
lib/hydra/works/models/concerns/file_set/virus_check.rb 100.00 % 23 3 3 0 1.00
lib/null_virus_scanner.rb 100.00 % 11 4 4 0 1.50
lib/provenance_logger.rb 83.33 % 12 6 5 1 0.83
lib/scheduler_logger.rb 85.71 % 16 7 6 1 0.86
lib/tasks/abstract_task.rb 50.00 % 53 26 13 13 0.50
lib/tasks/task_logger.rb 80.00 % 18 5 4 1 0.80
lib/umich_clamav_daemon_scanner.rb 45.71 % 159 70 32 38 0.63
lib/upload_logger.rb 85.71 % 16 7 6 1 0.86
spec/actors/hyrax/actors/data_set_actor_spec.rb 100.00 % 16 6 6 0 1.00
spec/actors/hyrax/actors/dissertation_actor_spec.rb 100.00 % 9 4 4 0 1.00
spec/actors/hyrax/actors/generic_work_actor_spec.rb 100.00 % 9 4 4 0 1.00
spec/authorities/qa/authorities/collections_spec.rb 75.68 % 82 37 28 9 1.05
spec/controllers/application_controller_spec.rb 100.00 % 99 50 50 0 1.26
spec/controllers/catalog_controller_spec.rb 100.00 % 17 8 8 0 1.00
spec/controllers/guest_user_message_controller_spec.rb 100.00 % 13 6 6 0 1.00
spec/controllers/hyrax/collections_controller_spec.rb 90.91 % 19 11 10 1 1.09
spec/controllers/hyrax/dashboard/collections_controller_spec.rb 100.00 % 259 148 148 0 1.24
spec/controllers/hyrax/data_sets_controller_spec.rb 90.00 % 38 10 9 1 0.90
spec/controllers/hyrax/deepblue_controller_spec.rb 100.00 % 41 20 20 0 1.00
spec/controllers/hyrax/dissertations_controller_spec.rb 100.00 % 9 4 4 0 1.00
spec/controllers/hyrax/file_sets_controller_spec.rb 100.00 % 107 56 56 0 1.14
spec/controllers/hyrax/generic_works_controller_spec.rb 100.00 % 9 4 4 0 1.00
spec/controllers/hyrax/my/collections_controller_spec.rb 100.00 % 12 7 7 0 1.14
spec/controllers/robots_controller_spec.rb 100.00 % 79 52 52 0 1.40
spec/factories/collection_types.rb 80.33 % 113 61 49 12 0.92
spec/factories/collections.rb 56.60 % 325 106 60 46 0.93
spec/factories/data_sets.rb 65.91 % 197 88 58 30 0.66
spec/factories/file_sets.rb 73.68 % 35 19 14 5 0.74
spec/factories/object_id.rb 66.67 % 7 3 2 1 0.67
spec/factories/permission_template_accesses.rb 100.00 % 16 9 9 0 1.00
spec/factories/permission_templates.rb 39.13 % 81 46 18 28 0.39
spec/factories/users.rb 63.33 % 61 30 19 11 7.30
spec/factories/workflows.rb 100.00 % 6 4 4 0 1.00
spec/features/create_data_set_spec.rb 75.00 % 88 16 12 4 0.94
spec/features/create_dissertation_spec.rb 75.00 % 74 16 12 4 0.94
spec/features/create_generic_work_spec.rb 75.00 % 72 16 12 4 0.94
spec/forms/hyrax/collection_form_spec.rb 100.00 % 40 5 5 0 1.40
spec/forms/hyrax/data_set_form_spec.rb 100.00 % 219 59 59 0 2.42
spec/forms/hyrax/dissertation_form_spec.rb 100.00 % 9 4 4 0 1.00
spec/forms/hyrax/generic_work_form_spec.rb 100.00 % 9 4 4 0 1.00
spec/helpers/deepblue/event_helper_spec.rb 100.00 % 103 69 69 0 1.32
spec/helpers/deepblue/logging_helper_spec.rb 100.00 % 172 90 90 0 1.63
spec/helpers/deepblue/provenance_helper_spec.rb 100.00 % 574 293 293 0 1.55
spec/integration/clamav_daemon_spec.rb 62.50 % 29 16 10 6 0.81
spec/jobs/about_to_expire_embargoes_job_spec.rb 100.00 % 125 64 64 0 1.38
spec/jobs/globus_copy_job_spec.rb 48.32 % 204 149 72 77 0.48
spec/jobs/globus_job_spec.rb 52.29 % 544 371 194 177 0.52
spec/jobs/globus_restart_all_job_spec.rb 95.00 % 153 100 95 5 1.54
spec/mailers/deepblue_mailer_spec.rb 100.00 % 17 8 8 0 1.00
spec/models/ability_spec.rb 88.00 % 37 25 22 3 1.16
spec/models/collection_spec.rb 100.00 % 7 4 4 0 1.00
spec/models/concerns/deepblue/abstract_event_behavior_spec.rb 100.00 % 153 88 88 0 1.48
spec/models/concerns/deepblue/metadata_behavior_spec.rb 97.40 % 129 77 75 2 1.94
spec/models/data_set_spec.rb 95.86 % 665 338 324 14 2.18
spec/models/dissertation_spec.rb 100.00 % 9 4 4 0 1.00
spec/models/file_set_spec.rb 78.05 % 799 123 96 27 0.89
spec/models/generic_work_spec.rb 100.00 % 9 4 4 0 1.00
spec/models/qa/local_authority_entry_spec.rb 100.00 % 5 3 3 0 1.00
spec/models/qa/local_authority_spec.rb 100.00 % 5 3 3 0 1.00
spec/models/search_builder_spec.rb 100.00 % 20 7 7 0 1.00
spec/models/user_spec.rb 100.00 % 265 33 33 0 1.18
spec/presenters/hyrax/admin_stats_presenter_spec.rb 100.00 % 78 52 52 0 1.77
spec/presenters/hyrax/data_set_presenter_spec.rb 100.00 % 469 40 40 0 2.68
spec/presenters/hyrax/dissertation_presenter_spec.rb 100.00 % 9 4 4 0 1.00
spec/presenters/hyrax/generic_work_presenter_spec.rb 100.00 % 9 4 4 0 1.00
spec/rails_helper.rb 100.00 % 82 23 23 0 54.48
spec/services/dataset/date_coverage_service_spec.rb 100.00 % 107 42 42 0 1.00
spec/services/deepblue/about_to_expire_embargoes_service_spec.rb 100.00 % 341 159 159 0 1.57
spec/services/deepblue/deactivate_expired_embargoes_service_spec.rb 100.00 % 241 109 109 0 1.22
spec/services/deepblue/doi_minting_service_spec.rb 97.78 % 71 45 44 1 2.24
spec/services/deepblue/log_exporter_spec.rb 100.00 % 152 84 84 0 1.25
spec/services/deepblue/log_reader_spec.rb 100.00 % 314 174 174 0 1.44
spec/services/deepblue/log_reporter_spec.rb 100.00 % 68 43 43 0 1.14
spec/services/deepblue/logging_callback_spec.rb 100.00 % 76 49 49 0 1.37
spec/services/deepblue/virus_scan_service_spec.rb 100.00 % 71 39 39 0 1.18
spec/services/deepblue/yaml_populate_service_spec.rb 99.67 % 1051 614 612 2 1.19
spec/support/factory_bot.rb 100.00 % 3 2 2 0 1.00
spec/support/factory_helpers.rb 80.00 % 24 5 4 1 0.80
spec/views/_user_util_links.html.erb_spec.rb 100.00 % 20 12 12 0 1.17

app/actors/hyrax/actors/abstract_event_actor.rb

66.67% lines covered

9 relevant lines. 6 lines covered and 3 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 module Actors
  4. 1 class AbstractEventActor < Hyrax::Actors::AbstractActor
  5. # LOG_IGNORE_EVENT = [].freeze
  6. 1 protected
  7. 1 def attributes_blank?( attributes )
  8. return true if attributes.blank?
  9. return true if [nil] == attributes
  10. false
  11. end
  12. 1 def log_event( env: )
  13. # # return if LOG_IGNORE_EVENT.include? key
  14. # actor = next_actor
  15. # from = caller_locations(1, 2)[1]
  16. # ::Deepblue::LoggingHelper.bold_debug ["from #{from}",
  17. # "env.curation_concern.class.name=#{env.curation_concern.class.name}",
  18. # "env.curation_concern.id=#{env.curation_concern&.id}",
  19. # "next_actor=#{next_actor.class.name}",
  20. # "env.attributes=#{env.attributes}" ]
  21. # rescue Exception => e # rubocop:disable Lint/RescueException
  22. # Rails.logger.error "log_event exception - #{e.class}: #{e.message} at #{e.backtrace[0]}"
  23. end
  24. end
  25. end
  26. end

app/actors/hyrax/actors/after_optimistic_lock_validator.rb

53.85% lines covered

13 relevant lines. 7 lines covered and 6 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 module Actors
  4. 1 class AfterOptimisticLockValidator < AbstractEventActor
  5. # @param [Hyrax::Actors::Environment] env
  6. # @return [Boolean] true if create was successful
  7. 1 def create( env )
  8. env.log_event( next_actor: next_actor )
  9. next_actor.create( env )
  10. end
  11. # @param [Hyrax::Actors::Environment] env
  12. # @return [Boolean] true if destroy was successful
  13. 1 def destroy( env )
  14. env.log_event( next_actor: next_actor )
  15. next_actor.destroy( env )
  16. end
  17. # @param [Hyrax::Actors::Environment] env
  18. # @return [Boolean] true if update was successful
  19. 1 def update( env )
  20. env.log_event( next_actor: next_actor )
  21. next_actor.update( env )
  22. end
  23. 1 protected
  24. # def log_event( env:, event: )
  25. # actor = next_actor
  26. # msg = "AfterOptimisticLockValidator.#{event}: env.curation_concern.class=#{env.curation_concern.class.name} next_actor=#{actor.class.name} env.attributes=#{ActiveSupport::JSON.encode env.attributes}"
  27. # Deepblue::LoggingHelper.bold_debug( msg, lines: 2 )
  28. # end
  29. end
  30. end
  31. end

app/actors/hyrax/actors/apply_order_actor.rb

23.81% lines covered

42 relevant lines. 10 lines covered and 32 lines missed.
    
  1. 1 module Hyrax
  2. 1 module Actors
  3. 1 class ApplyOrderActor < AbstractActor
  4. # @param [Hyrax::Actors::Environment] env
  5. # @return [Boolean] true if update was successful
  6. 1 def update(env)
  7. ::Deepblue::LoggingHelper.bold_debug "ApplyOrderActor.update: next_actor = #{next_actor.class.name}"
  8. ordered_member_ids = env.attributes.delete(:ordered_member_ids)
  9. sync_members(env, ordered_member_ids) &&
  10. apply_order(env.curation_concern, ordered_member_ids) &&
  11. next_actor.update(env)
  12. end
  13. 1 private
  14. 1 def can_edit_both_works?(env, work)
  15. rv = env.current_ability.can?(:edit, work) && env.current_ability.can?(:edit, env.curation_concern)
  16. # ::Deepblue::LoggingHelper.bold_debug "ApplyOrderActor.update: can_edit_both_works? = #{rv}"
  17. rv
  18. end
  19. 1 def sync_members(env, ordered_member_ids)
  20. ::Deepblue::LoggingHelper.bold_debug "ApplyOrderActor.sync_members ordered_member_ids = #{ordered_member_ids}"
  21. return true if ordered_member_ids.nil?
  22. cleanup_ids_to_remove_from_curation_concern(env.curation_concern, ordered_member_ids)
  23. add_new_work_ids_not_already_in_curation_concern(env, ordered_member_ids)
  24. env.curation_concern.errors[:ordered_member_ids].empty?
  25. end
  26. # @todo Why is this not doing work.save?
  27. # @see Hyrax::Actors::AddToWorkActor for duplication
  28. 1 def cleanup_ids_to_remove_from_curation_concern(curation_concern, ordered_member_ids)
  29. ::Deepblue::LoggingHelper.bold_debug "ApplyOrderActor.cleanup_ids_to_remove_from_curation_concern ordered_member_ids = #{ordered_member_ids}"
  30. (curation_concern.ordered_member_ids - ordered_member_ids).each do |old_id|
  31. work = ::ActiveFedora::Base.find(old_id)
  32. curation_concern.ordered_members.delete(work)
  33. curation_concern.members.delete(work)
  34. end
  35. end
  36. 1 def add_new_work_ids_not_already_in_curation_concern(env, ordered_member_ids)
  37. ::Deepblue::LoggingHelper.bold_debug "ApplyOrderActor.add_new_work_ids_not_already_in_curation_concern ordered_member_ids = #{ordered_member_ids}"
  38. (ordered_member_ids - env.curation_concern.ordered_member_ids).each do |work_id|
  39. work = ::ActiveFedora::Base.find(work_id)
  40. if can_edit_both_works?(env, work)
  41. env.curation_concern.ordered_members << work
  42. env.curation_concern.save!
  43. else
  44. env.curation_concern.errors[:ordered_member_ids] << "Works can only be related to each other if user has ability to edit both."
  45. end
  46. end
  47. end
  48. 1 def apply_order(curation_concern, new_order)
  49. ::Deepblue::LoggingHelper.bold_debug "ApplyOrderActor.apply_order new_order = #{new_order}"
  50. return true unless new_order
  51. curation_concern.ordered_member_proxies.each_with_index do |proxy, index|
  52. unless new_order[index]
  53. proxy.prev.next = curation_concern.ordered_member_proxies.last.next
  54. break
  55. end
  56. proxy.proxy_for = ActiveFedora::Base.id_to_uri(new_order[index])
  57. proxy.target = nil
  58. end
  59. curation_concern.list_source.order_will_change!
  60. true
  61. end
  62. end
  63. end
  64. end

app/actors/hyrax/actors/attach_members_actor.rb

25.58% lines covered

43 relevant lines. 11 lines covered and 32 lines missed.
    
  1. 1 module Hyrax
  2. 1 module Actors
  3. # Attach or remove child works to/from this work. This decodes parameters
  4. # that follow the rails nested parameters conventions:
  5. # e.g.
  6. # 'work_members_attributes' => {
  7. # '0' => { 'id' => '12312412'},
  8. # '1' => { 'id' => '99981228', '_destroy' => 'true' }
  9. # }
  10. #
  11. # The goal of this actor is to mutate the ordered_members with as few writes
  12. # as possible, because changing ordered_members is slow. This class only
  13. # writes changes, not the full ordered list.
  14. 1 class AttachMembersActor < Hyrax::Actors::AbstractActor
  15. # @param [Hyrax::Actors::Environment] env
  16. # @return [Boolean] true if update was successful
  17. 1 def update(env)
  18. # log_event( env: env )
  19. attributes_collection = env.attributes.delete(:work_members_attributes)
  20. ::Deepblue::LoggingHelper.bold_debug "AttachMembersActor.update: next_actor = #{next_actor.class.name}"
  21. assign_nested_attributes_for_collection(env, attributes_collection) &&
  22. next_actor.update(env)
  23. end
  24. 1 private
  25. # Attaches any unattached members. Deletes those that are marked _delete
  26. # @param [Hash<Hash>] a collection of members
  27. 1 def assign_nested_attributes_for_collection(env, attributes_collection)
  28. return true unless attributes_collection
  29. attributes_collection = attributes_collection.sort_by { |i, _| i.to_i }.map { |_, attributes| attributes }
  30. # checking for existing works to avoid rewriting/loading works that are
  31. # already attached
  32. existing_works = env.curation_concern.member_ids
  33. attributes_collection.each do |attributes|
  34. next if attributes['id'].blank?
  35. if existing_works.include?(attributes['id'])
  36. remove(env.curation_concern, attributes['id']) if has_destroy_flag?(attributes)
  37. else
  38. add(env, attributes['id'])
  39. end
  40. end
  41. end
  42. # Adds the item to the ordered members so that it displays in the items
  43. # along side the FileSets on the show page
  44. 1 def add2(env, id)
  45. member = ActiveFedora::Base.find(id)
  46. return unless env.current_ability.can?(:edit, member)
  47. env.curation_concern.ordered_members << member
  48. end
  49. # Remove the object from the members set and the ordered members list
  50. 1 def remove2(curation_concern, id)
  51. member = ActiveFedora::Base.find(id)
  52. curation_concern.ordered_members.delete(member)
  53. curation_concern.members.delete(member)
  54. end
  55. 1 def add( env, id )
  56. # ::Deepblue::LoggingHelper.bold_debug "AttachMembersActor.add: id = #{id}"
  57. return if id.blank?
  58. member = ActiveFedora::Base.find( id )
  59. # is this check necessary?
  60. can_do_it = env.current_ability.can?( :edit, member )
  61. # ::Deepblue::LoggingHelper.bold_debug "AttachMembersActor.add: id = #{id} can_do_it = #{can_do_it}"
  62. return unless can_do_it
  63. # ::Deepblue::LoggingHelper.bold_debug "AttachMembersActor.add: adding ordered member id = #{id}"
  64. env.curation_concern.ordered_members << member
  65. return unless env.curation_concern.respond_to? :provenance_child_add
  66. current_user = env.user
  67. env.curation_concern.provenance_child_add( current_user: current_user,
  68. child_id: id,
  69. event_note: "AttachMembersActor" )
  70. end
  71. # Remove the object from the members set and the ordered members list
  72. 1 def remove( curation_concern, id )
  73. # ::Deepblue::LoggingHelper.bold_debug "AttachMembersActor.remove: id = #{id}"
  74. return if id.blank?
  75. member = ActiveFedora::Base.find(id)
  76. curation_concern.ordered_members.delete(member)
  77. curation_concern.members.delete(member)
  78. return unless curation_concern.respond_to? :provenance_child_remove
  79. curation_concern.provenance_child_remove( current_user: current_user,
  80. child_id: id,
  81. event_note: "AttachMembersActor" )
  82. end
  83. # Determines if a hash contains a truthy _destroy key.
  84. # rubocop:disable Naming/PredicateName
  85. 1 def has_destroy_flag?(hash)
  86. ActiveFedora::Type::Boolean.new.cast(hash['_destroy'])
  87. end
  88. # rubocop:enable Naming/PredicateName
  89. end
  90. end
  91. end

app/actors/hyrax/actors/before_add_to_work_actor.rb

29.41% lines covered

34 relevant lines. 10 lines covered and 24 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 module Actors
  4. # see AddToWorkActor
  5. # provenance logging
  6. 1 class BeforeAddToWorkActor < AbstractEventActor
  7. # @param [Hyrax::Actors::Environment] env
  8. # @return [Boolean] true if create was successful
  9. 1 def create( env )
  10. env.log_event( next_actor: next_actor )
  11. work_ids = env.attributes.values_at( :in_works_ids )
  12. Deepblue::LoggingHelper.bold_debug "BeforeAddToWorkActor.create: next_actor = #{next_actor.class.name}, work_ids=#{work_ids}"
  13. actor = next_actor
  14. actor.create( env ) && add_to_works( env, work_ids )
  15. end
  16. # @param [Hyrax::Actors::Environment] env
  17. # @return [Boolean] true if update was successful
  18. 1 def update( env )
  19. env.log_event( next_actor: next_actor )
  20. work_ids = env.attributes.values_at( :in_works_ids )
  21. Deepblue::LoggingHelper.bold_debug "BeforeAddToWorkActor.update: next_actor = #{next_actor.class.name}, work_ids=#{work_ids}"
  22. actor = next_actor
  23. add_to_works( env, work_ids ) && actor.update( env )
  24. end
  25. 1 protected
  26. 1 def add_new_work_ids_not_already_in_curation_concern( env, new_work_ids )
  27. # add to new so long as the depositor for the parent and child matches, otherwise igmore
  28. (new_work_ids - env.curation_concern.in_works_ids).each do |work_id|
  29. work = ::ActiveFedora::Base.find( work_id )
  30. next unless work.respond_to? :provenance_child_add
  31. if can_edit_both_works?( env, work )
  32. work.provenance_child_add( current_user: env.user, child_id: env.curation_concern.id, event_note: 'BeforeAddToWorkActor' )
  33. end
  34. end
  35. end
  36. 1 def add_to_works( env, new_work_ids )
  37. return true if attributes_blank? new_work_ids
  38. cleanup_ids_to_remove_from_curation_concern( env, new_work_ids )
  39. add_new_work_ids_not_already_in_curation_concern(env, new_work_ids)
  40. env.curation_concern.errors[:in_works_ids].empty?
  41. end
  42. 1 def can_edit_both_works?( env, work )
  43. env.current_ability.can?( :edit, work ) && env.current_ability.can?( :edit, env.curation_concern )
  44. end
  45. 1 def cleanup_ids_to_remove_from_curation_concern( env, new_work_ids )
  46. (env.curation_concern.in_works_ids - new_work_ids).each do |old_id|
  47. work = ::ActiveFedora::Base.find( old_id )
  48. next unless work.respond_to? :provenance_child_remove
  49. work.provenance_child_remove( current_user: env.user, child_id: env.curation_concern.id, event_note: 'BeforeAddToWorkActor' )
  50. end
  51. end
  52. end
  53. end
  54. end

app/actors/hyrax/actors/before_attach_members_actor.rb

31.03% lines covered

29 relevant lines. 9 lines covered and 20 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 module Actors
  4. # see AttachMembersActor for original code
  5. # Provenance logging for:
  6. #
  7. # Attach or remove child works to/from this work. This decodes parameters
  8. # that follow the rails nested parameters conventions:
  9. # e.g.
  10. # 'work_members_attributes' => {
  11. # '0' => { 'id' = '12312412'},
  12. # '1' => { 'id' = '99981228', '_destroy' => 'true' }
  13. # }
  14. 1 class BeforeAttachMembersActor < AbstractEventActor
  15. # @param [Hyrax::Actors::Environment] env
  16. # @return [Boolean] true if update was successful
  17. 1 def update( env )
  18. env.log_event( next_actor: next_actor )
  19. attributes_collection = env.attributes.values_at( :work_members_attributes )
  20. Deepblue::LoggingHelper.bold_debug "BeforeAttachMembersActor.update: next_actor = #{next_actor.class.name}"
  21. assign_nested_attributes_for_collection( env, attributes_collection ) && next_actor.update( env )
  22. end
  23. 1 protected
  24. # Provenance log for attaching and unattaching members.
  25. # @param [Hash<Hash>] a collection of members
  26. 1 def assign_nested_attributes_for_collection( env, attributes_collection )
  27. return true if attributes_blank? attributes_collection
  28. return true unless env.curation_concern.respond_to? :provenance_child_add
  29. attributes_collection = attributes_collection.first if attributes_collection.is_a? Array
  30. attributes_collection = attributes_collection.sort_by { |i, _| i.to_i }.map { |_, attributes| attributes }
  31. # checking for existing works to avoid rewriting/loading works that are already attached
  32. existing_works = env.curation_concern.member_ids
  33. current_user = env.user
  34. attributes_collection.each do |attributes|
  35. next if attributes['id'].blank?
  36. if existing_works.include?( attributes['id'] )
  37. remove( env, attributes['id'], current_user ) if has_destroy_flag?( attributes )
  38. else
  39. add( env, attributes['id'], current_user )
  40. end
  41. end
  42. end
  43. # provenance log: Adds the item to the ordered members so that it displays in the items
  44. # along side the FileSets on the show page
  45. 1 def add( env, id, current_user )
  46. member = ActiveFedora::Base.find( id )
  47. return unless env.current_ability.can?( :edit, member )
  48. env.curation_concern.provenance_child_add( current_user: current_user, child_id: id, event_note: 'BeforeAttachMembersActor' )
  49. end
  50. # Determines if a hash contains a truthy _destroy key.
  51. # rubocop:disable Style/PredicateName
  52. 1 def has_destroy_flag?( hash )
  53. ActiveFedora::Type::Boolean.new.cast( hash['_destroy'] )
  54. end
  55. # rubocop:enable Style/PredicateName
  56. # provenance log for: Remove the object from the members set and the ordered members list
  57. 1 def remove( env, id, current_user )
  58. env.curation_concern.provenance_child_remove( current_user: current_user, child_id: id, event_note: 'BeforeAttachMembersActor' )
  59. end
  60. end
  61. end
  62. end

app/actors/hyrax/actors/before_model_actor.rb

53.85% lines covered

13 relevant lines. 7 lines covered and 6 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 module Actors
  4. 1 class BeforeModelActor < AbstractEventActor
  5. # @param [Hyrax::Actors::Environment] env
  6. # @return [Boolean] true if create was successful
  7. 1 def create( env )
  8. env.log_event( next_actor: next_actor )
  9. next_actor.create(env)
  10. end
  11. # @param [Hyrax::Actors::Environment] env
  12. # @return [Boolean] true if destroy was successful
  13. 1 def destroy( env )
  14. env.log_event( next_actor: next_actor )
  15. next_actor.destroy(env)
  16. end
  17. # @param [Hyrax::Actors::Environment] env
  18. # @return [Boolean] true if update was successful
  19. 1 def update( env )
  20. env.log_event( next_actor: next_actor )
  21. next_actor.update(env)
  22. end
  23. 1 protected
  24. # def log_before_event( env:, event: )
  25. # actor = next_actor
  26. # Deepblue::LoggingHelper.bold_debug "BeforeModelActor.#{event}: env.curation_concern.class=#{env.curation_concern.class.name} next_actor = #{actor.class.name}"
  27. # end
  28. # def model_actor(env)
  29. # actor_identifier = env.curation_concern.class
  30. # klass = "Hyrax::Actors::#{actor_identifier}Actor".constantize
  31. # klass.new(next_actor)
  32. # end
  33. end
  34. end
  35. end

app/actors/hyrax/actors/create_with_files_actor.rb

35.71% lines covered

28 relevant lines. 10 lines covered and 18 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 module Actors
  4. # Creates a work and attaches files to the work
  5. 1 class CreateWithFilesActor < Hyrax::Actors::AbstractActor
  6. # @param [Hyrax::Actors::Environment] env
  7. # @return [Boolean] true if create was successful
  8. 1 def create(env)
  9. uploaded_file_ids = filter_file_ids(env.attributes.delete(:uploaded_files))
  10. files = uploaded_files(uploaded_file_ids)
  11. validate_files(files, env) && next_actor.create(env) && attach_files(files, env)
  12. end
  13. # @param [Hyrax::Actors::Environment] env
  14. # @return [Boolean] true if update was successful
  15. 1 def update(env)
  16. uploaded_file_ids = filter_file_ids(env.attributes.delete(:uploaded_files))
  17. files = uploaded_files(uploaded_file_ids)
  18. validate_files(files, env) && next_actor.update(env) && attach_files(files, env)
  19. end
  20. 1 private
  21. 1 def filter_file_ids(input)
  22. Array.wrap(input).select(&:present?)
  23. end
  24. # ensure that the files we are given are owned by the depositor of the work
  25. 1 def validate_files(files, env)
  26. expected_user_id = env.user.id
  27. files.each do |file|
  28. if file.user_id != expected_user_id
  29. Rails.logger.error "User #{env.user.user_key} attempted to ingest uploaded_file #{file.id}, but it belongs to a different user"
  30. return false
  31. end
  32. end
  33. true
  34. end
  35. # @return [TrueClass]
  36. 1 def attach_files(files, env)
  37. return true if files.blank?
  38. AttachFilesToWorkJob.perform_later( env.curation_concern, files, env.user.user_key, env.attributes.to_h.symbolize_keys )
  39. true
  40. end
  41. # Fetch uploaded_files from the database
  42. 1 def uploaded_files(uploaded_file_ids)
  43. return [] if uploaded_file_ids.empty?
  44. UploadedFile.find(uploaded_file_ids)
  45. end
  46. end
  47. end
  48. end

app/actors/hyrax/actors/data_set_actor.rb

80.0% lines covered

5 relevant lines. 4 lines covered and 1 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 module Actors
  4. 1 class DataSetActor < Hyrax::Actors::BaseActor
  5. # Cast any singular values from the form to multiple values for persistence
  6. 1 def clean_attributes(attributes)
  7. # attributes[:rights_license] = Array(attributes[:rights_license]) if attributes.key? :rights_license
  8. super( attributes )
  9. end
  10. end
  11. end
  12. end

app/actors/hyrax/actors/dissertation_actor.rb

100.0% lines covered

3 relevant lines. 3 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work Dissertation`
  3. 1 module Hyrax
  4. 1 module Actors
  5. 1 class DissertationActor < Hyrax::Actors::BaseActor
  6. end
  7. end
  8. end

app/actors/hyrax/actors/generic_work_actor.rb

100.0% lines covered

3 relevant lines. 3 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work GenericWork`
  3. 1 module Hyrax
  4. 1 module Actors
  5. 1 class GenericWorkActor < Hyrax::Actors::BaseActor
  6. end
  7. end
  8. end

app/actors/hyrax/actors/interpret_visibility_actor.rb

50.0% lines covered

12 relevant lines. 6 lines covered and 6 lines missed.
    
  1. 1 require File.join(Gem::Specification.find_by_name("hyrax").full_gem_path, "app/actors/hyrax/actors/interpret_visibility_actor.rb")
  2. 1 module Hyrax
  3. 1 module Actors
  4. # monkey patch to allow embargo_release_date to be in the past
  5. 1 class InterpretVisibilityActor < AbstractActor
  6. 1 private
  7. # When specified, validate embargo is a future date that complies with AdminSet template requirements (if any)
  8. 1 def validate_embargo(env, intention, attributes, template)
  9. return true unless intention.wants_embargo?
  10. embargo_release_date = parse_date(attributes[:embargo_release_date])
  11. # Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  12. # Deepblue::LoggingHelper.called_from,
  13. # "before test",
  14. # "attributes=#{attributes}",
  15. # "embargo_release_date=#{embargo_release_date}" ]
  16. valid_embargo_release_date = DeepBlueDocs::Application.config.embargo_enforce_future_release_date ? valid_future_date?(env, embargo_release_date) : true
  17. # valid_template_embargo_date = valid_template_embargo_date?(env, embargo_release_date, template)
  18. # valid_template_visibility_after_embargo = valid_template_visibility_after_embargo?(env, attributes, template)
  19. # Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  20. # Deepblue::LoggingHelper.called_from,
  21. # "after test",
  22. # "valid_embargo_release_date=#{valid_embargo_release_date}",
  23. # "valid_template_embargo_date=#{valid_template_embargo_date}",
  24. # "valid_template_visibility_after_embargo=#{valid_template_visibility_after_embargo}" ]
  25. # When embargo required, date must be in future AND matches any template requirements
  26. return true if valid_embargo_release_date &&
  27. valid_template_embargo_date?(env, embargo_release_date, template) &&
  28. valid_template_visibility_after_embargo?(env, attributes, template)
  29. env.curation_concern.errors.add(:visibility, 'When setting visibility to "embargo" you must also specify embargo release date.') if embargo_release_date.blank?
  30. false
  31. end
  32. end
  33. end
  34. end

app/actors/hyrax/actors/optimistic_lock_validator.rb

64.29% lines covered

14 relevant lines. 9 lines covered and 5 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 module Actors
  4. # Validates that the submitted version is the most recent version in the datastore.
  5. # Caveat: we are not detecting if the version is changed by a different process between
  6. # the time this validator is run and when the object is saved
  7. 1 class OptimisticLockValidator < Actors::AbstractActor
  8. 1 class_attribute :version_field
  9. 1 self.version_field = 'version'
  10. # @param [Hyrax::Actors::Environment] env
  11. # @return [Boolean] true if update was successful
  12. 1 def update(env)
  13. # log_event( env: env )
  14. validate_lock(env, version_attribute(env.attributes)) && next_actor.update(env)
  15. end
  16. 1 private
  17. # @return [Boolean] returns true if the lock is missing or
  18. # if it matches the current object version.
  19. 1 def validate_lock(env, version)
  20. return true if version.blank? || version == env.curation_concern.etag
  21. env.curation_concern.errors.add(:base, :conflict)
  22. false
  23. end
  24. # Removes the version attribute
  25. 1 def version_attribute(attributes)
  26. attributes.delete(version_field)
  27. end
  28. end
  29. end
  30. end

app/controllers/application_controller.rb

68.57% lines covered

35 relevant lines. 24 lines covered and 11 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class ApplicationController < ActionController::Base
  3. 1 helper Openseadragon::OpenseadragonHelper
  4. # Adds a few additional behaviors into the application controller
  5. 1 include Blacklight::Controller
  6. 1 skip_after_action :discard_flash_if_xhr
  7. 1 include Hydra::Controller::ControllerBehavior
  8. # Behavior for devise. Use remote user field in http header for auth.
  9. 1 include Devise::Behaviors::HttpHeaderAuthenticatableBehavior
  10. # Adds Hyrax behaviors into the application controller
  11. 1 include Hyrax::Controller
  12. 1 include Hyrax::ThemedLayoutController
  13. 1 with_themed_layout '1_column'
  14. 1 protect_from_forgery with: :exception
  15. 1 around_action :global_request_logging
  16. 1 def global_request_logging
  17. 14 logger.info "ACCESS: #{request.remote_ip}, #{request.method} #{request.url}, #{request.headers['HTTP_USER_AGENT']}"
  18. begin
  19. 14 yield
  20. ensure
  21. 14 logger.info "response_status: #{response.status}"
  22. end
  23. end
  24. # From PSU's ScholarSphere
  25. # Clears any user session and authorization information by:
  26. # * forcing the session to be restarted on every request
  27. # * ensuring the user will be logged out if REMOTE_USER is not set
  28. # * clearing the entire session including flash messages
  29. 1 def clear_session_user
  30. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  31. # ::Deepblue::LoggingHelper.called_from,
  32. # "[AUTHN] clear_session_user: #{current_user.try(:email) || '(no user)'}",
  33. # "request=#{request}",
  34. # # "request&.keys=#{request&.keys}",
  35. # "session=#{session}",
  36. # "session&.keys=#{session&.keys}",
  37. # "params=#{params}",
  38. # "params.keys=#{params.keys}",
  39. # "" ]
  40. return nil_request if request.nil?
  41. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  42. # ::Deepblue::LoggingHelper.called_from,
  43. # "[AUTHN] clear_session_user: #{current_user.try(:email) || '(no user)'} request not nil",
  44. # "params=#{params}",
  45. # "" ]
  46. search = session[:search].dup if session[:search]
  47. flash = session[:flash].dup if session[:flash]
  48. request.env['warden'].logout unless user_logged_in?
  49. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  50. # ::Deepblue::LoggingHelper.called_from,
  51. # "[AUTHN] clear_session_user: #{current_user.try(:email) || '(no user)'}",
  52. # "After: request.env['warden'].logout unless user_logged_in?",
  53. # "request=#{request}",
  54. # # "request&.keys=#{request&.keys}",
  55. # "session=#{session}",
  56. # "session&.keys=#{session&.keys}",
  57. # "params=#{params}",
  58. # "params.keys=#{params.keys}",
  59. # "" ]
  60. session[:search] = search if search
  61. session[:flash] = flash if flash
  62. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  63. # ::Deepblue::LoggingHelper.called_from,
  64. # "[AUTHN] clear_session_user: #{current_user.try(:email) || '(no user)'}",
  65. # "After: session search and flash restored",
  66. # "request=#{request}",
  67. # # "request&.keys=#{request&.keys}",
  68. # "session=#{session}",
  69. # "session&.keys=#{session&.keys}",
  70. # "params=#{params}",
  71. # "params.keys=#{params.keys}",
  72. # "" ]
  73. end
  74. 1 Warden::Manager.after_authentication do |user, auth, opts|
  75. Rails.logger.debug "[AUTHN] Warden after_authentication (clearing flash): #{user}"
  76. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  77. # ::Deepblue::LoggingHelper.called_from,
  78. # "[AUTHN] Warden after_authentication (clearing flash): #{user}",
  79. # "" ]
  80. auth.request.flash.clear
  81. end
  82. 1 rescue_from ActionController::UnknownFormat, with: :rescue_404
  83. 1 def rescue_404
  84. 1 render file: Rails.public_path.join('404.html'), status: :not_found, layout: true
  85. end
  86. 1 before_action :set_locale
  87. 1 def set_locale
  88. 12 if params[:locale].present?
  89. I18n.locale = constrained_locale || I18n.default_locale
  90. params[:locale] = I18n.locale.to_s
  91. end
  92. end
  93. 1 def constrained_locale
  94. return params[:locale] if params[:locale].in?(Object.new.extend(HyraxHelper).available_translations)
  95. end
  96. end

app/controllers/catalog_controller.rb

100.0% lines covered

164 relevant lines. 164 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class CatalogController < ApplicationController
  3. 1 include Hydra::Catalog
  4. 1 include Hydra::Controller::ControllerBehavior
  5. # This filter applies the hydra access controls
  6. 1 before_action :enforce_show_permissions, only: :show
  7. 1 def self.uploaded_field
  8. 2 solr_name('system_create', :stored_sortable, type: :date)
  9. end
  10. 1 def self.modified_field
  11. 3 solr_name('system_modified', :stored_sortable, type: :date)
  12. end
  13. 1 configure_blacklight do |config|
  14. 1 config.view.gallery.partials = %i[index_header index]
  15. 1 config.view.masonry.partials = [:index]
  16. 1 config.view.slideshow.partials = [:index]
  17. # set maximum results per page to support bootstrap page sorting
  18. # in dashboard.
  19. # config.max_per_page = 1000000
  20. 1 config.show.tile_source_field = :content_metadata_image_iiif_info_ssm
  21. 1 config.show.partials.insert(1, :openseadragon)
  22. 1 config.search_builder_class = Hyrax::CatalogSearchBuilder
  23. # Show gallery view
  24. 1 config.view.gallery.partials = %i[index_header index]
  25. 1 config.view.slideshow.partials = [:index]
  26. ## Default parameters to send to solr for all search-like requests. See also SolrHelper#solr_search_params
  27. 1 config.default_solr_params = {
  28. qt: "search",
  29. rows: 10,
  30. # qf: "title_tesim description_tesim creator_tesim keyword_tesim"
  31. qf: "title_tesim name_tesim creator_tesim description_tesim grantnumber_tesim methodology_tesim subject_tesim keyword_tesim referenced_by_tesim all_text_timv"
  32. }
  33. # solr field configuration for document/show views
  34. 1 config.index.title_field = solr_name("title", :stored_searchable)
  35. 1 config.index.display_type_field = solr_name("has_model", :symbol)
  36. 1 config.index.thumbnail_field = 'thumbnail_path_ss'
  37. # solr fields that will be treated as facets by the blacklight application
  38. # The ordering of the field names is the order of the display
  39. #config.add_facet_field solr_name("human_readable_type", :facetable), label: "Type", limit: 5
  40. 1 config.add_facet_field solr_name("resource_type", :facetable), label: "Resource Type", limit: 5
  41. 1 config.add_facet_field solr_name("creator", :facetable), limit: 5
  42. #config.add_facet_field solr_name("contributor", :facetable), label: "Contributor", limit: 5
  43. #config.add_facet_field solr_name("keyword", :facetable), limit: 5
  44. #config.add_facet_field solr_name("subject", :facetable), limit: 5
  45. 1 config.add_facet_field solr_name("subject_discipline", :facetable), label: "Discipline", limit: 5
  46. 1 config.add_facet_field solr_name("language", :facetable), limit: 5
  47. #config.add_facet_field solr_name("based_near_label", :facetable), limit: 5
  48. #config.add_facet_field solr_name("publisher", :facetable), limit: 5
  49. #config.add_facet_field solr_name("file_format", :facetable), limit: 5
  50. #config.add_facet_field solr_name('member_of_collections', :symbol), limit: 5, label: 'Collections'
  51. # The generic_type isn't displayed on the facet list
  52. # It's used to give a label to the filter that comes from the user profile
  53. 1 config.add_facet_field solr_name("generic_type", :facetable), if: false
  54. # Have BL send all facet field names to Solr, which has been the default
  55. # previously. Simply remove these lines if you'd rather use Solr request
  56. # handler defaults, or have no facets.
  57. 1 config.add_facet_fields_to_solr_request!
  58. # solr fields to be displayed in the index (search results) view
  59. # The ordering of the field names is the order of the display
  60. 1 config.add_index_field solr_name("title", :stored_searchable), label: "Title", itemprop: 'name', if: false
  61. 1 config.add_index_field solr_name("creator", :stored_searchable), itemprop: 'creator', link_to_search: solr_name("creator", :facetable)
  62. 1 config.add_index_field solr_name("description", :stored_searchable), itemprop: 'description', helper_method: :iconify_auto_link
  63. 1 config.add_index_field solr_name("keyword", :stored_searchable), itemprop: 'keywords', link_to_search: solr_name("keyword", :facetable)
  64. 1 config.add_index_field solr_name("referenced_by", :stored_searchable), itemprop: 'referenced_by', label: "Citation to related publication", helper_method: :iconify_auto_link
  65. 1 config.add_index_field solr_name("subject_discipline", :stored_searchable), itemprop: 'subject_discipline', label: "Discipline", link_to_search: solr_name("subject_discipline", :facetable)
  66. # This was the default that came with hyrax.
  67. #config.add_index_field solr_name("title", :stored_searchable), label: "Title", itemprop: 'name', if: false
  68. #config.add_index_field solr_name("description", :stored_searchable), itemprop: 'description', helper_method: :iconify_auto_link
  69. #config.add_index_field solr_name("keyword", :stored_searchable), itemprop: 'keywords', link_to_search: solr_name("keyword", :facetable)
  70. #config.add_index_field solr_name("subject", :stored_searchable), itemprop: 'about', link_to_search: solr_name("subject", :facetable)
  71. #config.add_index_field solr_name("subject_discipline", :stored_searchable), label: "Discipline", link_to_search: solr_name("subject_discipline", :facetable)
  72. #config.add_index_field solr_name("creator", :stored_searchable), itemprop: 'creator', link_to_search: solr_name("creator", :facetable)
  73. #config.add_index_field solr_name("contributor", :stored_searchable), itemprop: 'contributor', link_to_search: solr_name("contributor", :facetable)
  74. #config.add_index_field solr_name("proxy_depositor", :symbol), label: "Depositor", helper_method: :link_to_profile
  75. #config.add_index_field solr_name("depositor"), label: "Owner", helper_method: :link_to_profile
  76. #config.add_index_field solr_name("publisher", :stored_searchable), itemprop: 'publisher', link_to_search: solr_name("publisher", :facetable)
  77. #config.add_index_field solr_name("based_near_label", :stored_searchable), itemprop: 'contentLocation', link_to_search: solr_name("based_near_label", :facetable)
  78. #config.add_index_field solr_name("language", :stored_searchable), itemprop: 'inLanguage', link_to_search: solr_name("language", :facetable)
  79. #config.add_index_field solr_name("date_uploaded", :stored_sortable, type: :date), itemprop: 'datePublished', helper_method: :human_readable_date
  80. #config.add_index_field solr_name("date_modified", :stored_sortable, type: :date), itemprop: 'dateModified', helper_method: :human_readable_date
  81. #config.add_index_field solr_name("date_created", :stored_searchable), itemprop: 'dateCreated', helper_method: :human_readable_date
  82. #config.add_index_field solr_name("rights_license", :stored_searchable), helper_method: :rights_license_links
  83. #config.add_index_field solr_name("rights_statement", :stored_searchable), helper_method: :rights_statement_links
  84. #config.add_index_field solr_name("license", :stored_searchable), helper_method: :license_links
  85. #config.add_index_field "total_file_size_lts", label: "Total File Size", helper_method: :human_readable_file_size
  86. #config.add_index_field solr_name("resource_type", :stored_searchable), label: "Resource Type", link_to_search: solr_name("resource_type", :facetable)
  87. #config.add_index_field solr_name("file_format", :stored_searchable), link_to_search: solr_name("file_format", :facetable)
  88. #config.add_index_field solr_name("identifier", :stored_searchable), helper_method: :index_field_link, field_name: 'identifier'
  89. #config.add_index_field solr_name("embargo_release_date", :stored_sortable, type: :date), label: "Embargo release date", helper_method: :human_readable_date
  90. #config.add_index_field solr_name("lease_expiration_date", :stored_sortable, type: :date), label: "Lease expiration date", helper_method: :human_readable_date
  91. #To be able to sort by title
  92. 1 config.add_index_field solr_name("title", :stored_sortable, type: :string), label: "Title"
  93. # solr fields to be displayed in the show (single result) view
  94. # The ordering of the field names is the order of the display
  95. 1 config.add_show_field solr_name("title", :stored_searchable)
  96. 1 config.add_show_field solr_name("description", :stored_searchable)
  97. 1 config.add_show_field solr_name("keyword", :stored_searchable)
  98. 1 config.add_show_field solr_name("subject", :stored_searchable)
  99. 1 config.add_show_field solr_name("subject_discipline", :stored_searchable)
  100. 1 config.add_show_field solr_name("creator", :stored_searchable)
  101. 1 config.add_show_field solr_name("contributor", :stored_searchable)
  102. 1 config.add_show_field solr_name("publisher", :stored_searchable)
  103. 1 config.add_show_field solr_name("based_near_label", :stored_searchable)
  104. 1 config.add_show_field solr_name("language", :stored_searchable)
  105. 1 config.add_show_field solr_name("date_created", :stored_searchable)
  106. 1 config.add_show_field solr_name("date_modified", :stored_searchable)
  107. 1 config.add_show_field solr_name("date_published", :stored_searchable), label: "Published"
  108. 1 config.add_show_field "date_published_dtsim"
  109. 1 config.add_show_field solr_name("date_uploaded", :stored_searchable)
  110. 1 config.add_show_field solr_name("rights_license", :stored_searchable)
  111. 1 config.add_show_field solr_name("rights_statement", :stored_searchable)
  112. 1 config.add_show_field solr_name("license", :stored_searchable)
  113. 1 config.add_show_field "total_file_size_lts"
  114. 1 config.add_show_field solr_name("resource_type", :stored_searchable), label: "Resource Type"
  115. 1 config.add_show_field solr_name("format", :stored_searchable)
  116. 1 config.add_show_field solr_name("identifier", :stored_searchable)
  117. 1 config.add_show_field solr_name("referenced_by", :stored_searchable), label: "Citation to related publication"
  118. 1 config.add_show_field solr_name("date_coverage", :stored_searchable), label: "Date Coverage"
  119. # "fielded" search configuration. Used by pulldown among other places.
  120. # For supported keys in hash, see rdoc for Blacklight::SearchFields
  121. #
  122. # Search fields will inherit the :qt solr request handler from
  123. # config[:default_solr_parameters], OR can specify a different one
  124. # with a :qt key/value. Below examples inherit, except for subject
  125. # that specifies the same :qt as default for our own internal
  126. # testing purposes.
  127. #
  128. # The :key is what will be used to identify this BL search field internally,
  129. # as well as in URLs -- so changing it after deployment may break bookmarked
  130. # urls. A display label will be automatically calculated from the :key,
  131. # or can be specified manually to be different.
  132. #
  133. # This one uses all the defaults set by the solr request handler. Which
  134. # solr request handler? The one set in config[:default_solr_parameters][:qt],
  135. # since we aren't specifying it otherwise.
  136. 1 config.add_search_field('all_fields', label: 'All Fields') do |field|
  137. 1 all_names = config.show_fields.values.map(&:field).join(" ")
  138. 1 title_name = solr_name("title", :stored_searchable)
  139. 1 field.solr_parameters = {
  140. qf: "#{all_names} file_format_tesim all_text_timv",
  141. pf: title_name.to_s
  142. }
  143. end
  144. # Now we see how to over-ride Solr request handler defaults, in this
  145. # case for a BL "search field", which is really a dismax aggregate
  146. # of Solr search fields.
  147. # creator, title, description, publisher, date_created,
  148. # subject, language, resource_type, format, identifier, based_near,
  149. 1 config.add_search_field('based_near') do |field|
  150. 1 field.label = "Location"
  151. 1 solr_name = solr_name("based_near_label", :stored_searchable)
  152. 1 field.solr_local_parameters = {
  153. qf: solr_name,
  154. pf: solr_name
  155. }
  156. end
  157. 1 config.add_search_field('contributor') do |field|
  158. # solr_parameters hash are sent to Solr as ordinary url query params.
  159. # :solr_local_parameters will be sent using Solr LocalParams
  160. # syntax, as eg {! qf=$title_qf }. This is neccesary to use
  161. # Solr parameter de-referencing like $title_qf.
  162. # See: http://wiki.apache.org/solr/LocalParams
  163. 1 solr_name = solr_name("contributor", :stored_searchable)
  164. 1 field.solr_local_parameters = {
  165. qf: solr_name,
  166. pf: solr_name
  167. }
  168. end
  169. 1 config.add_search_field('creator') do |field|
  170. 1 solr_name = solr_name("creator", :stored_searchable)
  171. 1 field.solr_local_parameters = {
  172. qf: solr_name,
  173. pf: solr_name
  174. }
  175. end
  176. 1 config.add_search_field('date_created') do |field|
  177. 1 solr_name = solr_name("created", :stored_searchable)
  178. 1 field.solr_local_parameters = {
  179. qf: solr_name,
  180. pf: solr_name
  181. }
  182. end
  183. 1 config.add_search_field('depositor') do |field|
  184. 1 solr_name = solr_name("depositor", :symbol)
  185. 1 field.solr_local_parameters = {
  186. qf: solr_name,
  187. pf: solr_name
  188. }
  189. end
  190. 1 config.add_search_field('description') do |field|
  191. 1 field.label = "Abstract or Summary"
  192. 1 solr_name = solr_name("description", :stored_searchable)
  193. 1 field.solr_local_parameters = {
  194. qf: solr_name,
  195. pf: solr_name
  196. }
  197. end
  198. 1 config.add_search_field('doi') do |field|
  199. 1 field.label = "Doi"
  200. 1 solr_name = solr_name("doi_label", :stored_searchable)
  201. 1 field.solr_local_parameters = {
  202. qf: solr_name,
  203. pf: solr_name
  204. }
  205. end
  206. 1 config.add_search_field('format') do |field|
  207. 1 solr_name = solr_name("format", :stored_searchable)
  208. 1 field.solr_local_parameters = {
  209. qf: solr_name,
  210. pf: solr_name
  211. }
  212. end
  213. 1 config.add_search_field('fundedby') do |field|
  214. 1 field.label = "Funded By"
  215. 1 solr_name = solr_name("fundedby_label", :stored_searchable)
  216. 1 field.solr_local_parameters = {
  217. qf: solr_name,
  218. pf: solr_name
  219. }
  220. end
  221. 1 config.add_search_field('access_deepblue') do |field|
  222. 1 field.label = "Article access to DataCORE"
  223. 1 solr_name = solr_name("access_deepblue_label", :stored_searchable)
  224. 1 field.solr_local_parameters = {
  225. qf: solr_name,
  226. pf: solr_name
  227. }
  228. end
  229. 1 config.add_search_field('fundedby_other') do |field|
  230. 1 field.label = "Funded By Other"
  231. 1 solr_name = solr_name("fundedby_other_label", :stored_searchable)
  232. 1 field.solr_local_parameters = {
  233. qf: solr_name,
  234. pf: solr_name
  235. }
  236. end
  237. 1 config.add_search_field('grantnumber') do |field|
  238. 1 field.label = "Grant number"
  239. 1 solr_name = solr_name("grantnumber_label", :stored_searchable)
  240. 1 field.solr_local_parameters = {
  241. qf: solr_name,
  242. pf: solr_name
  243. }
  244. end
  245. 1 config.add_search_field('identifier') do |field|
  246. 1 solr_name = solr_name("id", :stored_searchable)
  247. 1 field.solr_local_parameters = {
  248. qf: solr_name,
  249. pf: solr_name
  250. }
  251. end
  252. 1 config.add_search_field('keyword') do |field|
  253. 1 solr_name = solr_name("keyword", :stored_searchable)
  254. 1 field.solr_local_parameters = {
  255. qf: solr_name,
  256. pf: solr_name
  257. }
  258. end
  259. 1 config.add_search_field('language') do |field|
  260. 1 solr_name = solr_name("language", :stored_searchable)
  261. 1 field.solr_local_parameters = {
  262. qf: solr_name,
  263. pf: solr_name
  264. }
  265. end
  266. 1 config.add_search_field('license') do |field|
  267. 1 solr_name = solr_name("license", :stored_searchable)
  268. 1 field.solr_local_parameters = {
  269. qf: solr_name,
  270. pf: solr_name
  271. }
  272. end
  273. 1 config.add_search_field('methodology') do |field|
  274. 1 field.label = "Methodology"
  275. 1 solr_name = solr_name("methodology_label", :stored_searchable)
  276. 1 field.solr_local_parameters = {
  277. qf: solr_name,
  278. pf: solr_name
  279. }
  280. end
  281. 1 config.add_search_field('prior_identifier') do |field|
  282. 1 field.label = "Prior Identifier"
  283. 1 solr_name = solr_name("prior_identifier", :stored_searchable)
  284. 1 field.solr_local_parameters = {
  285. qf: solr_name,
  286. pf: solr_name
  287. }
  288. end
  289. 1 config.add_search_field('publisher') do |field|
  290. 1 solr_name = solr_name("publisher", :stored_searchable)
  291. 1 field.solr_local_parameters = {
  292. qf: solr_name,
  293. pf: solr_name
  294. }
  295. end
  296. 1 config.add_search_field('referenced_by') do |field|
  297. 1 field.label = "Citation to related publication"
  298. 1 solr_name = solr_name("referenced_by", :stored_searchable)
  299. 1 field.solr_local_parameters = {
  300. qf: solr_name,
  301. pf: solr_name
  302. }
  303. end
  304. 1 config.add_search_field('resource_type') do |field|
  305. 1 solr_name = solr_name("resource_type", :stored_searchable)
  306. 1 field.solr_local_parameters = {
  307. qf: solr_name,
  308. pf: solr_name
  309. }
  310. end
  311. 1 config.add_search_field('rights_license') do |field|
  312. 1 solr_name = solr_name("rights_license", :stored_searchable)
  313. 1 field.solr_local_parameters = {
  314. qf: solr_name,
  315. pf: solr_name
  316. }
  317. end
  318. 1 config.add_search_field('rights_license_other') do |field|
  319. 1 solr_name = solr_name("rights_license_other", :stored_searchable)
  320. 1 field.solr_local_parameters = {
  321. qf: solr_name,
  322. pf: solr_name
  323. }
  324. end
  325. 1 config.add_search_field('rights_statement') do |field|
  326. 1 solr_name = solr_name("rights_statement", :stored_searchable)
  327. 1 field.solr_local_parameters = {
  328. qf: solr_name,
  329. pf: solr_name
  330. }
  331. end
  332. 1 config.add_search_field('subject') do |field|
  333. 1 solr_name = solr_name("subject", :stored_searchable)
  334. 1 field.solr_local_parameters = {
  335. qf: solr_name,
  336. pf: solr_name
  337. }
  338. end
  339. 1 config.add_search_field('subject_discipline') do |field|
  340. 1 solr_name = solr_name("subject_discipline", :stored_searchable)
  341. 1 field.solr_local_parameters = {
  342. qf: solr_name,
  343. pf: solr_name
  344. }
  345. end
  346. 1 config.add_search_field('title') do |field|
  347. 1 solr_name = solr_name("title", :stored_searchable)
  348. 1 field.solr_local_parameters = {
  349. qf: solr_name,
  350. pf: solr_name
  351. }
  352. end
  353. 1 config.add_search_field('total_file_size') do |field|
  354. 1 solr_name = solr_name("total_file_size", :stored_searchable)
  355. 1 field.solr_local_parameters = {
  356. qf: solr_name,
  357. pf: solr_name
  358. }
  359. end
  360. # "sort results by" select (pulldown)
  361. # label in pulldown is followed by the name of the SOLR field to sort by and
  362. # whether the sort is ascending or descending (it must be asc or desc
  363. # except in the relevancy case).
  364. # label is key, solr field is value
  365. 1 config.add_sort_field "score desc, #{modified_field} desc", label: "relevance"
  366. 1 config.add_sort_field "#{uploaded_field} desc", label: "date created \u25BC"
  367. 1 config.add_sort_field "#{uploaded_field} asc", label: "date created \u25B2"
  368. 1 config.add_sort_field "#{modified_field} desc", label: "last modified \u25BC"
  369. 1 config.add_sort_field "#{modified_field} asc", label: "last modified \u25B2"
  370. # Need to reindex the collection to be able to use these.
  371. # config.add_sort_field "titl_ssi desc", label: "date modified \u25BC"
  372. # config.add_sort_field "title_ssi asc", label: "date modified \u25B2"
  373. # If there are more than this many search results, no spelling ("did you
  374. # mean") suggestion is offered.
  375. 1 config.spell_max = 5
  376. end
  377. # disable the bookmark control from displaying in gallery view
  378. # Hyrax doesn't show any of the default controls on the list view, so
  379. # this method is not called in that context.
  380. 1 def render_bookmarks_control?
  381. 1 false
  382. end
  383. end

app/controllers/concerns/deepblue/works_controller_behavior.rb

41.18% lines covered

17 relevant lines. 7 lines covered and 10 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 module WorksControllerBehavior
  4. 1 extend ActiveSupport::Concern
  5. #in umrdr
  6. #include Hyrax::Controller
  7. 1 include Hyrax::WorksControllerBehavior
  8. 1 include Deepblue::ControllerWorkflowEventBehavior
  9. 1 def after_update_response
  10. if curation_concern.file_sets.present?
  11. return redirect_to main_app.copy_access_hyrax_permission_path(curation_concern) if permissions_changed?
  12. return redirect_to main_app.confirm_hyrax_permission_path(curation_concern) if curation_concern.visibility_changed?
  13. end
  14. respond_to do |wants|
  15. wants.html { redirect_to [main_app, curation_concern], notice: "Work \"#{curation_concern}\" successfully updated." }
  16. wants.json { render :show, status: :ok, location: polymorphic_path([main_app, curation_concern]) }
  17. end
  18. end
  19. # override curation concerns, add form fields values
  20. 1 def build_form
  21. super
  22. # Set up the multiple parameters for the date coverage attribute in the form
  23. cov_date = Date.edtf(@form.date_coverage)
  24. cov_params = Dataset::DateCoverageService.interval_to_params cov_date
  25. @form.merge_date_coverage_attributes! cov_params
  26. end
  27. end
  28. end

app/controllers/concerns/hyrax/breadcrumbs.rb

33.33% lines covered

27 relevant lines. 9 lines covered and 18 lines missed.
    
  1. 1 module Hyrax
  2. 1 module Breadcrumbs
  3. 1 extend ActiveSupport::Concern
  4. 1 def build_breadcrumbs
  5. if request.referer
  6. trail_from_referer
  7. else
  8. default_trail
  9. end
  10. end
  11. 1 def default_trail_start
  12. add_breadcrumb I18n.t('hyrax.controls.home'), hyrax.root_path
  13. add_breadcrumb I18n.t('hyrax.dashboard.title'), hyrax.dashboard_path if user_signed_in?
  14. end
  15. 1 def default_trail
  16. #add_breadcrumb I18n.t('hyrax.controls.home'), hyrax.root_path
  17. #add_breadcrumb I18n.t('hyrax.dashboard.title'), hyrax.dashboard_path if user_signed_in?
  18. case request.referer
  19. when /catalog/
  20. add_breadcrumb I18n.t('hyrax.controls.home'), hyrax.root_path
  21. add_breadcrumb I18n.t('hyrax.dashboard.title'), hyrax.dashboard_path if user_signed_in?
  22. else
  23. default_trail_start
  24. add_breadcrumb_for_controller if user_signed_in?
  25. begin
  26. add_breadcrumb_for_action # errors when parent is missing
  27. rescue
  28. # noop
  29. end
  30. end
  31. end
  32. 1 def trail_from_referer
  33. case request.referer
  34. when /catalog/
  35. add_breadcrumb I18n.t('hyrax.controls.home'), hyrax.root_path
  36. add_breadcrumb I18n.t('hyrax.bread_crumb.search_results'), request.referer
  37. else
  38. default_trail_start
  39. add_breadcrumb_for_controller if user_signed_in?
  40. add_breadcrumb_for_action
  41. end
  42. end
  43. # Override these in your controller
  44. 1 def add_breadcrumb_for_controller; end
  45. # Override these in your controller
  46. 1 def add_breadcrumb_for_action; end
  47. end
  48. end

app/controllers/concerns/hyrax/collections_controller_behavior.rb

48.39% lines covered

62 relevant lines. 30 lines covered and 32 lines missed.
    
  1. 1 module Hyrax
  2. 1 module CollectionsControllerBehavior
  3. 1 extend ActiveSupport::Concern
  4. 1 include Blacklight::AccessControls::Catalog
  5. 1 include Blacklight::Base
  6. 1 included do
  7. # include the display_trophy_link view helper method
  8. 1 helper Hyrax::TrophyHelper
  9. # This is needed as of BL 3.7
  10. 1 copy_blacklight_config_from(::CatalogController)
  11. 1 class_attribute :presenter_class,
  12. :form_class,
  13. :single_item_search_builder_class,
  14. :membership_service_class
  15. 1 self.presenter_class = Hyrax::CollectionPresenter
  16. # The search builder to find the collection
  17. 1 self.single_item_search_builder_class = SingleCollectionSearchBuilder
  18. # The search builder to find the collections' members
  19. 1 self.membership_service_class = Collections::CollectionMemberService
  20. end
  21. 1 def create
  22. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  23. # Deepblue::LoggingHelper.called_from,
  24. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  25. # "params[:id]=#{params[:id]}",
  26. # "params=#{params}" ]
  27. super
  28. end
  29. 1 def destroy
  30. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  31. # Deepblue::LoggingHelper.called_from,
  32. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  33. # "params[:id]=#{params[:id]}",
  34. # "params=#{params}" ]
  35. super
  36. end
  37. 1 def edit
  38. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  39. # Deepblue::LoggingHelper.called_from,
  40. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  41. # "params[:id]=#{params[:id]}",
  42. # "params=#{params}" ]
  43. super
  44. end
  45. 1 def show
  46. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  47. # Deepblue::LoggingHelper.called_from,
  48. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  49. # "params[:id]=#{params[:id]}",
  50. # "params=#{params}" ]
  51. @curation_concern ||= ActiveFedora::Base.find(params[:id])
  52. presenter
  53. query_collection_members
  54. end
  55. 1 def update
  56. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  57. # Deepblue::LoggingHelper.called_from,
  58. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  59. # "params[:id]=#{params[:id]}",
  60. # "params=#{params}" ]
  61. super
  62. end
  63. 1 def collection
  64. action_name == 'show' ? @presenter : @collection
  65. end
  66. 1 private
  67. 1 def presenter
  68. @presenter ||= begin
  69. # Query Solr for the collection.
  70. # run the solr query to find the collection members
  71. response = repository.search(single_item_search_builder.query)
  72. curation_concern = response.documents.first
  73. raise CanCan::AccessDenied unless curation_concern
  74. presenter_class.new(curation_concern, current_ability)
  75. end
  76. end
  77. # Instantiates the search builder that builds a query for a single item
  78. # this is useful in the show view.
  79. 1 def single_item_search_builder
  80. single_item_search_builder_class.new(self).with(params.except(:q, :page))
  81. end
  82. 1 def collection_params
  83. form_class.model_attributes(params[:collection])
  84. end
  85. # Include 'catalog' and 'hyrax/base' in the search path for views, while prefering
  86. # our local paths. Thus we are unable to just override `self.local_prefixes`
  87. 1 def _prefixes
  88. @_prefixes ||= super + ['catalog', 'hyrax/base']
  89. end
  90. 1 def query_collection_members
  91. member_works
  92. member_subcollections if collection.collection_type.nestable?
  93. parent_collections if collection.collection_type.nestable? && action_name == 'show'
  94. end
  95. # Instantiate the membership query service
  96. 1 def collection_member_service
  97. @collection_member_service ||= membership_service_class.new(scope: self, collection: collection, params: params_for_query)
  98. end
  99. 1 def member_works
  100. @response = collection_member_service.available_member_works
  101. @member_docs = @response.documents
  102. @members_count = @response.total
  103. end
  104. 1 def parent_collections
  105. page = params[:parent_collection_page].to_i
  106. query = Hyrax::Collections::NestedCollectionQueryService
  107. collection.parent_collections = query.parent_collections(child: collection_object, scope: self, page: page)
  108. end
  109. 1 def collection_object
  110. action_name == 'show' ? Collection.find(collection.id) : collection
  111. end
  112. 1 def member_subcollections
  113. results = collection_member_service.available_member_subcollections
  114. @subcollection_solr_response = results
  115. @subcollection_docs = results.documents
  116. @subcollection_count = @presenter.subcollection_count = results.total
  117. end
  118. # You can override this method if you need to provide additional inputs to the search
  119. # builder. For example:
  120. # search_field: 'all_fields'
  121. # @return <Hash> the inputs required for the collection member query service
  122. 1 def params_for_query
  123. params.merge(q: params[:cq])
  124. end
  125. end
  126. end

app/controllers/concerns/hyrax/works_controller_behavior.rb

30.0% lines covered

30 relevant lines. 9 lines covered and 21 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require File.join( Gem::Specification.find_by_name("hyrax").full_gem_path, "app/controllers/concerns/hyrax/works_controller_behavior.rb" )
  3. 1 module Hyrax
  4. 1 module WorksControllerBehavior
  5. 1 private
  6. 1 def curation_concern_from_search_results
  7. search_params = params
  8. search_params.delete :page
  9. search_result_document(search_params)
  10. end
  11. # Only returns unsuppressed documents the user has read access to
  12. 1 def search_result_document(search_params)
  13. _, document_list = search_results(search_params)
  14. return document_list.first unless document_list.empty?
  15. document_not_found!
  16. rescue Blacklight::Exceptions::RecordNotFound => e
  17. unless user_signed_in?
  18. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  19. # ::Deepblue::LoggingHelper.called_from,
  20. # "about to redirect - 01",
  21. # "" ]
  22. return redirect_to guest_user_message_url, alert: "unable to present requested work"
  23. end
  24. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  25. # ::Deepblue::LoggingHelper.called_from,
  26. # "e=#{e}",
  27. # "" ] # + e.backtrace
  28. begin
  29. # check with Fedora to see if the requested id was deleted
  30. id = params[:id]
  31. ActiveFedora::Base.find( id )
  32. rescue Ldp::Gone => gone
  33. # it was deleted
  34. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  35. # ::Deepblue::LoggingHelper.called_from,
  36. # "gone=#{gone.class} #{gone.message} at #{gone.backtrace[0]}",
  37. # "" ]
  38. # okay, since this looks like a deleted curation concern, we can check the provenance log
  39. # if admin, redirect to the provenance log controller
  40. if current_ability.admin?
  41. # url = provenance_log_url
  42. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  43. # ::Deepblue::LoggingHelper.called_from,
  44. # "about to redirect to url=#{url}",
  45. # "" ]
  46. return redirect_to( provenance_log_url, alert: "\"#{id}\" was deleted." )
  47. end
  48. rescue ActiveFedora::ObjectNotFoundError => e2
  49. if current_ability.admin?
  50. # nope, never existed
  51. # url = provenance_log_url
  52. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  53. # ::Deepblue::LoggingHelper.called_from,
  54. # "e2=#{e2.class} #{e2.message} at #{e2.backtrace[0]}",
  55. # "about to redirect - 02a - url=#{url}",
  56. # "" ]
  57. return redirect_to( provenance_log_url, alert: "\"#{id}\" not found." )
  58. end
  59. end
  60. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  61. # ::Deepblue::LoggingHelper.called_from,
  62. # "about to redirect - 02 - guest_user_message_url=#{guest_user_message_url}",
  63. # "" ]
  64. return redirect_to( guest_user_message_url, alert: "unable to present requested work" )
  65. end
  66. 1 def document_not_found!
  67. doc = ::SolrDocument.find(params[:id])
  68. raise WorkflowAuthorizationException if doc.suppressed? && current_ability.can?(:read, doc)
  69. raise CanCan::AccessDenied.new(nil, :show)
  70. end
  71. 1 def provenance_log_url
  72. id = params[:id]
  73. Rails.application.routes.url_helpers.url_for( only_path: true,
  74. action: 'show',
  75. controller: 'provenance_log',
  76. id: id )
  77. # guest_user_message_url
  78. end
  79. 1 def guest_user_message_url
  80. Rails.application.routes.url_helpers.url_for( only_path: true,
  81. action: 'show',
  82. controller: 'guest_user_message' )
  83. end
  84. end
  85. end

app/controllers/deepblue/collections_controller_behavior.rb

37.5% lines covered

32 relevant lines. 12 lines covered and 20 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 module CollectionsControllerBehavior
  4. 1 include Deepblue::ControllerWorkflowEventBehavior
  5. 1 PARAMS_KEY = 'collection'
  6. ## Provenance log
  7. 1 def provenance_log_update_after
  8. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  9. # Deepblue::LoggingHelper.called_from,
  10. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  11. # "@update_attr_key_values=#{@update_attr_key_values}",
  12. # "" ]
  13. curation_concern.provenance_log_update_after( current_user: current_user,
  14. event_note: default_event_note,
  15. update_attr_key_values: @update_attr_key_values )
  16. end
  17. 1 def provenance_log_update_before
  18. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  19. # Deepblue::LoggingHelper.called_from,
  20. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  21. # "@update_attr_key_values=#{@update_attr_key_values}",
  22. # "" ]
  23. return unless @update_attr_key_values.nil?
  24. @update_attr_key_values = curation_concern.provenance_log_update_before( form_params: params[params_key].dup )
  25. end
  26. ## end Provenance log
  27. ## visibility / publish
  28. 1 def visiblity_changed
  29. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  30. # Deepblue::LoggingHelper.called_from,
  31. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  32. # "" ]
  33. @update_attr_key_values = curation_concern.provenance_log_update_before( form_params: params[PARAMS_KEY].dup )
  34. if visibility_to_private?
  35. mark_as_set_to_private
  36. elsif visibility_to_public?
  37. mark_as_set_to_public
  38. end
  39. end
  40. 1 def visibility_changed_update
  41. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  42. # Deepblue::LoggingHelper.called_from,
  43. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  44. # "" ]
  45. if curation_concern.private? && @visibility_changed_to_private
  46. workflow_unpublish
  47. elsif curation_concern.public? && @visibility_changed_to_public
  48. workflow_publish
  49. end
  50. end
  51. 1 def visibility_to_private?
  52. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  53. # Deepblue::LoggingHelper.called_from,
  54. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  55. # "" ]
  56. return false if curation_concern.private?
  57. params[params_key]['visibility'] == Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
  58. end
  59. 1 def visibility_to_public?
  60. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  61. # Deepblue::LoggingHelper.called_from,
  62. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  63. # "" ]
  64. return false if curation_concern.public?
  65. params[params_key]['visibility'] == Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
  66. end
  67. 1 def mark_as_set_to_private
  68. @visibility_changed_to_public = false
  69. @visibility_changed_to_private = true
  70. end
  71. 1 def mark_as_set_to_public
  72. @visibility_changed_to_public = true
  73. @visibility_changed_to_private = false
  74. end
  75. ## end visibility / publish
  76. end
  77. end

app/controllers/deepblue/controller_workflow_event_behavior.rb

50.0% lines covered

16 relevant lines. 8 lines covered and 8 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 module ControllerWorkflowEventBehavior
  4. 1 def workflow_create
  5. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  6. Deepblue::LoggingHelper.called_from,
  7. Deepblue::LoggingHelper.obj_class( 'class', self ),
  8. "current_user=#{current_user}",
  9. "" ]
  10. curation_concern.workflow_create( current_user: current_user,
  11. event_note: "#{self.class.name} - deposited by #{curation_concern.depositor}" )
  12. end
  13. 1 def workflow_destroy
  14. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  15. Deepblue::LoggingHelper.called_from,
  16. Deepblue::LoggingHelper.obj_class( 'class', self ),
  17. "current_user=#{current_user}",
  18. "" ]
  19. curation_concern.workflow_destroy( current_user: current_user, event_note: "#{self.class.name}" )
  20. end
  21. 1 def workflow_publish
  22. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  23. Deepblue::LoggingHelper.called_from,
  24. Deepblue::LoggingHelper.obj_class( 'class', self ),
  25. "current_user=#{current_user}",
  26. "" ]
  27. curation_concern.workflow_publish( current_user: current_user, event_note: "#{self.class.name}" )
  28. end
  29. 1 def workflow_unpublish
  30. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  31. Deepblue::LoggingHelper.called_from,
  32. Deepblue::LoggingHelper.obj_class( 'class', self ),
  33. "current_user=#{current_user}",
  34. "" ]
  35. curation_concern.workflow_unpublish( current_user: current_user, event_note: "#{self.class.name}" )
  36. end
  37. 1 def workflow_update_before( current_user:, event_note: "" )
  38. end
  39. 1 def workflow_update_after( current_user:, event_note: "" )
  40. end
  41. end
  42. end

app/controllers/guest_user_message_controller.rb

100.0% lines covered

6 relevant lines. 6 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. # due to double redirecting for guest users (those who aren't logged in) when directing them back to
  3. # the main app window, the flash message is lost
  4. # so create a specialized window for displaying messages
  5. 1 class GuestUserMessageController < ApplicationController
  6. 1 class_attribute :presenter_class
  7. 1 self.presenter_class = GuestUserMessagePresenter
  8. 1 def show
  9. 1 @presenter = presenter_class.new( controller: self )
  10. 1 render '/guest_user_message'
  11. end
  12. end

app/controllers/hyrax/collections_controller.rb

47.89% lines covered

71 relevant lines. 34 lines covered and 37 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 class CollectionsController < DeepblueController
  4. 1 EVENT_NOTE = 'Hyrax::CollectionsController'
  5. 1 PARAMS_KEY = 'collection'
  6. 1 include Hyrax::CollectionsControllerBehavior
  7. 1 include Deepblue::ControllerWorkflowEventBehavior
  8. 1 include BreadcrumbsForCollections
  9. 1 before_action :deepblue_collections_controller_debug
  10. 1 before_action :workflow_destroy, only: [:destroy]
  11. 1 before_action :provenance_log_update_before, only: [:update]
  12. 1 before_action :visiblity_changed, only: [:update]
  13. 1 after_action :workflow_create, only: [:create]
  14. 1 after_action :provenance_log_update_after, only: [:update]
  15. 1 after_action :visibility_changed_update, only: [:update]
  16. 1 protect_from_forgery with: :null_session, only: [:display_provenance_log]
  17. 1 with_themed_layout :decide_layout
  18. 1 load_and_authorize_resource except: %i[index show create], instance_name: :collection
  19. 1 def deepblue_collections_controller_debug
  20. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  21. Deepblue::LoggingHelper.called_from,
  22. "params=#{params}" ]
  23. end
  24. # Renders a JSON response with a list of files in this collection
  25. # This is used by the edit form to populate the thumbnail_id dropdown
  26. 1 def files
  27. result = form.select_files.map do |label, id|
  28. { id: id, text: label }
  29. end
  30. render json: result
  31. end
  32. 1 def curation_concern
  33. @collection ||= ActiveFedora::Base.find(params[:id])
  34. end
  35. ## Provenance log
  36. 1 def provenance_log_update_after
  37. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  38. # Deepblue::LoggingHelper.called_from,
  39. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  40. # "" ]
  41. curation_concern.provenance_log_update_after( current_user: current_user,
  42. # event_note: 'CollectionsController.provenance_log_update_after',
  43. update_attr_key_values: @update_attr_key_values )
  44. end
  45. 1 def provenance_log_update_before
  46. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  47. # Deepblue::LoggingHelper.called_from,
  48. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  49. # "@update_attr_key_values=#{@update_attr_key_values}",
  50. # "" ]
  51. return unless @update_attr_key_values.nil?
  52. @update_attr_key_values = curation_concern.provenance_log_update_before( form_params: params[PARAMS_KEY].dup )
  53. end
  54. ## end Provenance log
  55. ## display provenance log
  56. 1 def display_provenance_log
  57. # load provenance log for this work
  58. id = @collection.id # curation_concern.id
  59. file_path = Deepblue::ProvenancePath.path_for_reference( id )
  60. Deepblue::LoggingHelper.bold_debug [ "CollectionsController", "display_provenance_log", file_path ]
  61. Deepblue::ProvenanceLogService.entries( id, refresh: true )
  62. # continue on to normal display
  63. #redirect_to [main_app, curation_concern]
  64. redirect_back fallback_location: root_url
  65. end
  66. 1 def display_provenance_log_enabled?
  67. true
  68. end
  69. 1 def provenance_log_entries_present?
  70. provenance_log_entries.present?
  71. end
  72. ## end display provenance log
  73. ## visibility / publish
  74. 1 def visiblity_changed
  75. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  76. # Deepblue::LoggingHelper.called_from,
  77. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  78. # "" ]
  79. @update_attr_key_values = curation_concern.provenance_log_update_before( form_params: params[PARAMS_KEY].dup )
  80. if visibility_to_private?
  81. mark_as_set_to_private
  82. elsif visibility_to_public?
  83. mark_as_set_to_public
  84. end
  85. end
  86. 1 def visibility_changed_update
  87. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  88. # Deepblue::LoggingHelper.called_from,
  89. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  90. # "" ]
  91. if curation_concern.private? && @visibility_changed_to_private
  92. workflow_unpublish
  93. elsif curation_concern.public? && @visibility_changed_to_public
  94. workflow_publish
  95. end
  96. end
  97. 1 def visibility_to_private?
  98. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  99. # Deepblue::LoggingHelper.called_from,
  100. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  101. # "" ]
  102. return false if curation_concern.private?
  103. params[PARAMS_KEY]['visibility'] == Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
  104. end
  105. 1 def visibility_to_public?
  106. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  107. # Deepblue::LoggingHelper.called_from,
  108. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  109. # "" ]
  110. return false if curation_concern.public?
  111. params[PARAMS_KEY]['visibility'] == Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
  112. end
  113. 1 def mark_as_set_to_private
  114. @visibility_changed_to_public = false
  115. @visibility_changed_to_private = true
  116. end
  117. 1 def mark_as_set_to_public
  118. @visibility_changed_to_public = true
  119. @visibility_changed_to_private = false
  120. end
  121. ## end visibility / publish
  122. 1 private
  123. 1 def form
  124. @form ||= form_class.new( @collection, current_ability, repository )
  125. end
  126. 1 def decide_layout
  127. layout = case action_name
  128. when 'show'
  129. '1_column'
  130. else
  131. 'dashboard'
  132. end
  133. File.join( theme, layout )
  134. end
  135. end
  136. end

app/controllers/hyrax/dashboard/collections_controller.rb

100.0% lines covered

45 relevant lines. 45 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require File.join( Gem::Specification.find_by_name("hyrax").full_gem_path, "app/controllers/hyrax/dashboard/collections_controller.rb" )
  3. 1 module Hyrax
  4. 1 module Dashboard
  5. # monkey patch Hyrax::Dashboard::CollectionsController
  6. ## Shows a list of all collections to the admins
  7. 1 class CollectionsController < Hyrax::My::CollectionsController
  8. 1 include ::Hyrax::BrandingHelper
  9. 1 include Deepblue::CollectionsControllerBehavior
  10. 1 EVENT_NOTE = 'Hyrax::Dashboard::CollectionsController'
  11. 1 PARAMS_KEY = 'collection'
  12. ## begin monkey patch overrides
  13. 1 alias_method :monkey_after_create, :after_create
  14. 1 alias_method :monkey_destroy, :destroy
  15. 1 def after_create
  16. 1 monkey_after_create
  17. 1 workflow_create
  18. end
  19. 1 def destroy
  20. 1 workflow_destroy
  21. 1 monkey_destroy
  22. end
  23. 1 def show
  24. 3 if @collection.collection_type.brandable?
  25. 2 banner_info = collection_banner_info( id: @collection.id )
  26. 2 @banner = brand_path( collection_branding_info: banner_info.first ) unless banner_info.empty?
  27. end
  28. 3 presenter
  29. 3 query_collection_members
  30. end
  31. ## end monkey patch overrides
  32. 1 before_action :provenance_log_update_before, only: [:update]
  33. 1 after_action :provenance_log_update_after, only: [:update]
  34. 1 def curation_concern
  35. 2 @collection ||= ActiveFedora::Base.find(params[:id])
  36. end
  37. 1 def default_event_note
  38. 1 EVENT_NOTE
  39. end
  40. 1 def params_key
  41. 1 PARAMS_KEY
  42. end
  43. ## begin monkey patch banner
  44. 1 def process_banner_input
  45. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  46. # ::Deepblue::LoggingHelper.called_from,
  47. # "@collection.id = #{@collection.id}",
  48. # "" ]
  49. 3 return update_existing_banner if params["banner_unchanged"] == "true"
  50. 2 remove_banner
  51. 2 uploaded_file_ids = params["banner_files"]
  52. 2 add_new_banner(uploaded_file_ids) if uploaded_file_ids
  53. end
  54. 1 def update_existing_banner
  55. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  56. # ::Deepblue::LoggingHelper.called_from,
  57. # "@collection.id = #{@collection.id}",
  58. # "" ]
  59. 1 banner_info = collection_banner_info( id: @collection.id )
  60. 1 banner_info.first.save(banner_info.first.local_path, false)
  61. end
  62. 1 def add_new_banner(uploaded_file_ids)
  63. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  64. # ::Deepblue::LoggingHelper.called_from,
  65. # "@collection.id = #{@collection.id}",
  66. # "uploaded_file_ids = #{uploaded_file_ids}",
  67. # "" ]
  68. 1 f = uploaded_files(uploaded_file_ids).first
  69. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  70. # ::Deepblue::LoggingHelper.called_from,
  71. # "@collection.id = #{@collection.id}",
  72. # "f.file_url = #{f.file_url}",
  73. # "" ]
  74. 1 banner_info = CollectionBrandingInfo.new(
  75. collection_id: @collection.id,
  76. filename: File.split(f.file_url).last,
  77. role: "banner",
  78. alt_txt: "",
  79. target_url: ""
  80. )
  81. 1 banner_info.save f.file_url
  82. end
  83. 1 def remove_banner
  84. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  85. # ::Deepblue::LoggingHelper.called_from,
  86. # "@collection.id = #{@collection.id}",
  87. # "" ]
  88. 1 banner_info = collection_banner_info( id: @collection.id )
  89. 1 banner_info&.delete_all
  90. end
  91. ## end monkey patch banner
  92. end
  93. end
  94. end

app/controllers/hyrax/data_sets_controller.rb

30.74% lines covered

257 relevant lines. 79 lines covered and 178 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 class DataSetsController < DeepblueController
  4. 1 PARAMS_KEY = 'data_set'
  5. 1 include Deepblue::WorksControllerBehavior
  6. 1 self.curation_concern_type = ::DataSet
  7. 1 self.show_presenter = Hyrax::DataSetPresenter
  8. 1 before_action :assign_date_coverage, only: %i[create update]
  9. 1 before_action :assign_admin_set, only: %i[create update]
  10. 1 before_action :workflow_destroy, only: [:destroy]
  11. 1 before_action :provenance_log_update_before, only: [:update]
  12. 1 before_action :visiblity_changed, only: [:update]
  13. 1 before_action :prepare_permissions, only: [:show]
  14. 1 after_action :workflow_create, only: [:create]
  15. 1 after_action :visibility_changed_update, only: [:update]
  16. 1 after_action :provenance_log_update_after, only: [:update]
  17. 1 after_action :reset_permissions, only: [:show]
  18. 1 protect_from_forgery with: :null_session, only: [:display_provenance_log]
  19. 1 protect_from_forgery with: :null_session, only: [:globus_add_email]
  20. 1 protect_from_forgery with: :null_session, only: [:globus_download]
  21. 1 protect_from_forgery with: :null_session, only: [:globus_download_add_email]
  22. 1 protect_from_forgery with: :null_session, only: [:globus_download_notify_me]
  23. 1 protect_from_forgery with: :null_session, only: [:zip_download]
  24. 1 attr_accessor :user_email_one, :user_email_two
  25. 1 attr_accessor :provenance_log_entries
  26. # These methods (prepare_permissions, and reset_permissions) are used so that
  27. # when viewing a tombstoned work, and the user is not admin, the user
  28. # will be able to see the metadata.
  29. 1 def prepare_permissions
  30. if current_ability.admin?
  31. else
  32. # Need to add admin group to current_ability
  33. # or presenter will not be accessible.
  34. current_ability.user_groups << "admin"
  35. if presenter&.tombstone.present?
  36. else
  37. current_ability.user_groups.delete("admin")
  38. end
  39. end
  40. end
  41. 1 def reset_permissions
  42. current_ability.user_groups.delete("admin")
  43. end
  44. ## box integration
  45. 1 def box_create_dir_and_add_collaborator
  46. return nil unless DeepBlueDocs::Application.config.box_integration_enabled
  47. user_email = Deepblue::EmailHelper.user_email_from( current_user )
  48. BoxHelper.create_dir_and_add_collaborator( curation_concern.id, user_email: user_email )
  49. end
  50. 1 def box_link
  51. return nil unless DeepBlueDocs::Application.config.box_integration_enabled
  52. BoxHelper.box_link( curation_concern.id )
  53. end
  54. 1 def box_work_created
  55. box_create_dir_and_add_collaborator
  56. end
  57. ## end box integration
  58. ## date_coverage
  59. # Create EDTF::Interval from form parameters
  60. # Replace the date coverage parameter prior with serialization of EDTF::Interval
  61. 1 def assign_date_coverage
  62. cov_interval = Dataset::DateCoverageService.params_to_interval params
  63. params[PARAMS_KEY]['date_coverage'] = cov_interval ? cov_interval.edtf : ""
  64. end
  65. 1 def assign_admin_set
  66. admin_sets = Hyrax::AdminSetService.new(self).search_results(:deposit)
  67. admin_sets.each do |admin_set|
  68. if admin_set.id != "admin_set/default"
  69. params[PARAMS_KEY]['admin_set_id'] = admin_set.id
  70. end
  71. end
  72. end
  73. # end date_coverage
  74. ## DOI
  75. 1 def doi
  76. doi_mint
  77. respond_to do |wants|
  78. wants.html { redirect_to [main_app, curation_concern] }
  79. wants.json do
  80. render :show,
  81. status: :ok,
  82. location: polymorphic_path([main_app, curation_concern])
  83. end
  84. end
  85. end
  86. 1 def doi_minting_enabled?
  87. ::Deepblue::DoiBehavior::DOI_MINTING_ENABLED
  88. end
  89. 1 def doi_mint
  90. # Do not mint doi if
  91. # one already exists
  92. # work file_set count is 0.
  93. if curation_concern.doi_pending?
  94. flash[:notice] = MsgHelper.t( 'data_set.doi_is_being_minted' )
  95. elsif curation_concern.doi_minted?
  96. flash[:notice] = MsgHelper.t( 'data_set.doi_already_exists' )
  97. elsif curation_concern.file_sets.count < 1
  98. flash[:notice] = MsgHelper.t( 'data_set.doi_requires_work_with_files' )
  99. elsif ( curation_concern.depositor != current_user.email ) && !current_ability.admin?
  100. flash[:notice] = MsgHelper.t( 'data_set.doi_user_without_access' )
  101. elsif curation_concern.doi_mint( current_user: current_user, event_note: 'DataSetsController' )
  102. flash[:notice] = MsgHelper.t( 'data_set.doi_minting_started' )
  103. end
  104. end
  105. # def mint_doi_enabled?
  106. # true
  107. # end
  108. ## end DOI
  109. ## Globus
  110. 1 def globus_add_email
  111. if user_signed_in?
  112. user_email = Deepblue::EmailHelper.user_email_from( current_user )
  113. globus_copy_job( user_email: user_email, delay_per_file_seconds: 0 )
  114. flash_and_go_back globus_files_prepping_msg( user_email: user_email )
  115. elsif params[:user_email_one].present? || params[:user_email_two].present?
  116. user_email_one = params[:user_email_one].present? ? params[:user_email_one].strip : ''
  117. user_email_two = params[:user_email_two].present? ? params[:user_email_two].strip : ''
  118. # if user_email_one === user_email_two
  119. if user_email_one == user_email_two
  120. globus_copy_job( user_email: user_email_one, delay_per_file_seconds: 0 )
  121. flash_and_redirect_to_main_cc globus_files_prepping_msg( user_email: user_email_one )
  122. else
  123. flash.now[:error] = emails_did_not_match_msg( user_email_one, user_email_two )
  124. render 'globus_download_add_email_form'
  125. end
  126. else
  127. flash_and_redirect_to_main_cc globus_status_msg
  128. end
  129. end
  130. 1 def globus_clean_download
  131. ::GlobusCleanJob.perform_later( curation_concern.id, clean_download: true )
  132. globus_ui_delay
  133. dirs = []
  134. dirs << ::GlobusJob.target_download_dir( curation_concern.id )
  135. dirs << ::GlobusJob.target_prep_dir( curation_concern.id, prefix: nil )
  136. dirs << ::GlobusJob.target_prep_tmp_dir( curation_concern.id, prefix: nil )
  137. flash_and_redirect_to_main_cc globus_clean_msg( dirs )
  138. end
  139. 1 def globus_clean_prep
  140. ::GlobusCleanJob.perform_later( curation_concern.id, clean_download: false )
  141. globus_ui_delay
  142. end
  143. 1 def globus_complete?
  144. ::GlobusJob.copy_complete? curation_concern.id
  145. end
  146. 1 def globus_copy_job( user_email: nil,
  147. delay_per_file_seconds: DeepBlueDocs::Application.config.globus_debug_delay_per_file_copy_job_seconds )
  148. ::GlobusCopyJob.perform_later( curation_concern.id,
  149. user_email: user_email,
  150. delay_per_file_seconds: delay_per_file_seconds )
  151. globus_ui_delay
  152. end
  153. 1 def globus_download
  154. if globus_complete?
  155. flash_and_redirect_to_main_cc globus_files_available_here
  156. else
  157. user_email = Deepblue::EmailHelper.user_email_from( current_user, user_signed_in: user_signed_in? )
  158. msg = if globus_prepping?
  159. globus_files_prepping_msg( user_email: user_email )
  160. else
  161. globus_file_prep_started_msg( user_email: user_email )
  162. end
  163. if user_signed_in?
  164. globus_copy_job( user_email: user_email )
  165. flash_and_redirect_to_main_cc msg
  166. else
  167. render 'globus_download_notify_me_form'
  168. end
  169. end
  170. end
  171. 1 def globus_download_add_email
  172. if user_signed_in?
  173. globus_add_email
  174. else
  175. render 'globus_download_add_email_form'
  176. end
  177. end
  178. 1 def globus_download_enabled?
  179. DeepBlueDocs::Application.config.globus_enabled
  180. end
  181. 1 def globus_download_notify_me
  182. if user_signed_in?
  183. user_email = Deepblue::EmailHelper.user_email_from( current_user )
  184. globus_copy_job( user_email: user_email )
  185. flash_and_go_back globus_file_prep_started_msg( user_email: user_email )
  186. elsif params[:user_email_one].present? || params[:user_email_two].present?
  187. user_email_one = params[:user_email_one].present? ? params[:user_email_one].strip : ''
  188. user_email_two = params[:user_email_two].present? ? params[:user_email_two].strip : ''
  189. # if user_email_one === user_email_two
  190. if user_email_one == user_email_two
  191. globus_copy_job( user_email: user_email_one )
  192. flash_and_redirect_to_main_cc globus_file_prep_started_msg( user_email: user_email_one )
  193. else
  194. # flash_and_go_back emails_did_not_match_msg( user_email_one, user_email_two )
  195. flash.now[:error] = emails_did_not_match_msg( user_email_one, user_email_two )
  196. render 'globus_download_notify_me_form'
  197. end
  198. else
  199. globus_copy_job( user_email: nil )
  200. flash_and_redirect_to_main_cc globus_file_prep_started_msg
  201. end
  202. end
  203. 1 def globus_enabled?
  204. DeepBlueDocs::Application.config.globus_enabled
  205. end
  206. 1 def globus_last_error_msg
  207. ::GlobusJob.error_file_contents curation_concern.id
  208. end
  209. 1 def globus_prepping?
  210. ::GlobusJob.files_prepping? curation_concern.id
  211. end
  212. 1 def globus_ui_delay( delay_seconds: DeepBlueDocs::Application.config.globus_after_copy_job_ui_delay_seconds )
  213. sleep delay_seconds if delay_seconds.positive?
  214. end
  215. 1 def globus_url
  216. ::GlobusJob.external_url curation_concern.id
  217. end
  218. ## end Globus
  219. ## Provenance log
  220. 1 def provenance_log_update_after
  221. curation_concern.provenance_log_update_after( current_user: current_user,
  222. # event_note: 'DataSetsController.provenance_log_update_after',
  223. update_attr_key_values: @update_attr_key_values )
  224. end
  225. 1 def provenance_log_update_before
  226. @update_attr_key_values = curation_concern.provenance_log_update_before( form_params: params[PARAMS_KEY].dup )
  227. end
  228. ## end Provenance log
  229. ## display provenance log
  230. 1 def display_provenance_log
  231. # load provenance log for this work
  232. file_path = Deepblue::ProvenancePath.path_for_reference( curation_concern.id )
  233. Deepblue::LoggingHelper.bold_debug [ "DataSetsController", "display_provenance_log", file_path ]
  234. Deepblue::ProvenanceLogService.entries( curation_concern.id, refresh: true )
  235. # continue on to normal display
  236. redirect_to polymorphic_url([main_app, curation_concern], anchor: "prov_log")
  237. end
  238. 1 def display_provenance_log_enabled?
  239. true
  240. end
  241. 1 def provenance_log_entries_present?
  242. provenance_log_entries.present?
  243. end
  244. ## end display provenance log
  245. ## Tombstone
  246. 1 def tombstone
  247. epitaph = params[:tombstone]
  248. success = curation_concern.entomb!( epitaph, current_user )
  249. msg = if success
  250. MsgHelper.t( 'data_set.tombstone_notice', title: curation_concern.title.first.to_s, reason: epitaph.to_s )
  251. else
  252. "#{curation_concern.title.first} is already tombstoned."
  253. end
  254. redirect_to dashboard_works_path, notice: msg
  255. end
  256. 1 def tombstone_enabled?
  257. true
  258. end
  259. ## End Tombstone
  260. ## visibility / publish
  261. 1 def visiblity_changed
  262. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  263. # Deepblue::LoggingHelper.called_from,
  264. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  265. # "" ]
  266. if visibility_to_private?
  267. mark_as_set_to_private
  268. elsif visibility_to_public?
  269. mark_as_set_to_public
  270. end
  271. end
  272. 1 def visibility_changed_update
  273. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  274. # Deepblue::LoggingHelper.called_from,
  275. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  276. # "" ]
  277. if curation_concern.private? && @visibility_changed_to_private
  278. workflow_unpublish
  279. elsif curation_concern.public? && @visibility_changed_to_public
  280. workflow_publish
  281. end
  282. end
  283. 1 def visibility_to_private?
  284. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  285. # Deepblue::LoggingHelper.called_from,
  286. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  287. # "" ]
  288. return false if curation_concern.private?
  289. params[PARAMS_KEY]['visibility'] == Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
  290. end
  291. 1 def visibility_to_public?
  292. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  293. # Deepblue::LoggingHelper.called_from,
  294. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  295. # "" ]
  296. return false if curation_concern.public?
  297. params[PARAMS_KEY]['visibility'] == Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
  298. end
  299. 1 def mark_as_set_to_private
  300. @visibility_changed_to_public = false
  301. @visibility_changed_to_private = true
  302. end
  303. 1 def mark_as_set_to_public
  304. @visibility_changed_to_public = true
  305. @visibility_changed_to_private = false
  306. end
  307. ## end visibility / publish
  308. ## begin zip download operations
  309. 1 def zip_download
  310. require 'zip'
  311. require 'tempfile'
  312. tmp_dir = Settings.tmpdir || '/tmp'
  313. tmp_dir = Pathname.new tmp_dir
  314. # Deepblue::LoggingHelper.debug "Download Zip begin tmp_dir #{tmp_dir}"
  315. Deepblue::LoggingHelper.bold_debug [ "zip_download begin", "tmp_dir=#{tmp_dir}" ]
  316. target_dir = target_dir_name_id( tmp_dir, curation_concern.id )
  317. # Deepblue::LoggingHelper.debug "Download Zip begin copy to folder #{target_dir}"
  318. Deepblue::LoggingHelper.bold_debug [ "zip_download", "target_dir=#{target_dir}" ]
  319. Dir.mkdir( target_dir ) unless Dir.exist?( target_dir )
  320. target_zipfile = target_dir_name_id( target_dir, curation_concern.id, ".zip" )
  321. # Deepblue::LoggingHelper.debug "Download Zip begin copy to target_zipfile #{target_zipfile}"
  322. Deepblue::LoggingHelper.bold_debug [ "zip_download", "target_zipfile=#{target_zipfile}" ]
  323. File.delete target_zipfile if File.exist? target_zipfile
  324. # clean the zip directory if necessary, since the zip structure is currently flat, only
  325. # have to clean files in the target folder
  326. files = Dir.glob( (target_dir.join '*').to_s)
  327. Deepblue::LoggingHelper.bold_debug files, label: "zip_download files to delete:"
  328. files.each do |file|
  329. File.delete file if File.exist? file
  330. end
  331. Deepblue::LoggingHelper.debug "Download Zip begin copy to folder #{target_dir}"
  332. Deepblue::LoggingHelper.bold_debug [ "zip_download", "begin copy target_dir=#{target_dir}" ]
  333. Zip::File.open(target_zipfile.to_s, Zip::File::CREATE ) do |zipfile|
  334. metadata_filename = curation_concern.metadata_report( dir: target_dir )
  335. zipfile.add( metadata_filename.basename, metadata_filename )
  336. export_file_sets_to( target_dir: target_dir, log_prefix: "Zip: " ) do |target_file_name, target_file|
  337. zipfile.add( target_file_name, target_file )
  338. end
  339. end
  340. # Deepblue::LoggingHelper.debug "Download Zip copy complete to folder #{target_dir}"
  341. Deepblue::LoggingHelper.bold_debug [ "zip_download", "download complete target_dir=#{target_dir}" ]
  342. send_file target_zipfile.to_s
  343. end
  344. 1 def zip_download_enabled?
  345. Settings.zip_download_enabled
  346. end
  347. # end zip download operations
  348. # # Create EDTF::Interval from form parameters
  349. # # Replace the date coverage parameter prior with serialization of EDTF::Interval
  350. # def assign_date_coverage
  351. # ##cov_interval = Umrdr::DateCoverageService.params_to_interval params
  352. # ##params['generic_work']['date_coverage'] = cov_interval ? [cov_interval.edtf] : []
  353. # end
  354. #
  355. # def check_recent_uploads
  356. # if params[:uploads_since]
  357. # begin
  358. # @recent_uploads = [];
  359. # uploads_since = Time.at(params[:uploads_since].to_i / 1000.0)
  360. # presenter.file_set_presenters.reverse_each do |file_set|
  361. # date_uploaded = get_date_uploaded_from_solr(file_set)
  362. # if date_uploaded.nil? or date_uploaded < uploads_since
  363. # break
  364. # end
  365. # @recent_uploads.unshift file_set
  366. # end
  367. # rescue Exception => e
  368. # Rails.logger.info "Something happened in check_recent_uploads: #{params[:uploads_since]} : #{e.message}"
  369. # end
  370. # end
  371. # end
  372. 1 protected
  373. 1 def emails_did_not_match_msg( _user_email_one, _user_email_two )
  374. "Emails did not match" # + ": '#{user_email_one}' != '#{user_email_two}'"
  375. end
  376. 1 def export_file_sets_to( target_dir:,
  377. log_prefix: "",
  378. do_export_predicate: ->(_target_file_name, _target_file) { true },
  379. quiet: false,
  380. &block )
  381. file_sets = curation_concern.file_sets
  382. Deepblue::ExportFilesHelper.export_file_sets( target_dir: target_dir,
  383. file_sets: file_sets,
  384. log_prefix: log_prefix,
  385. do_export_predicate: do_export_predicate,
  386. quiet: quiet,
  387. &block )
  388. end
  389. 1 def flash_and_go_back( msg )
  390. Deepblue::LoggingHelper.debug msg
  391. redirect_back fallback_location: root_url, notice: msg
  392. end
  393. 1 def flash_error_and_go_back( msg )
  394. Deepblue::LoggingHelper.debug msg
  395. redirect_back fallback_location: root_url, alert: msg
  396. end
  397. 1 def flash_and_redirect_to_main_cc( msg )
  398. Deepblue::LoggingHelper.debug msg
  399. redirect_to [main_app, curation_concern], notice: msg
  400. end
  401. 1 def globus_clean_msg( dir )
  402. dirs = dir.join( MsgHelper.t( 'data_set.globus_clean_join_html' ) )
  403. rv = MsgHelper.t( 'data_set.globus_clean', dirs: dirs )
  404. return rv
  405. end
  406. 1 def globus_file_prep_started_msg( user_email: nil )
  407. MsgHelper.t( 'data_set.globus_file_prep_started',
  408. when_available: globus_files_when_available( user_email: user_email ) )
  409. end
  410. 1 def globus_files_prepping_msg( user_email: nil )
  411. MsgHelper.t( 'data_set.globus_files_prepping',
  412. when_available: globus_files_when_available( user_email: user_email ) )
  413. end
  414. 1 def globus_files_when_available( user_email: nil )
  415. if user_email.nil?
  416. MsgHelper.t( 'data_set.globus_files_when_available' )
  417. else
  418. MsgHelper.t( 'data_set.globus_files_when_available_email', user_email: user_email )
  419. end
  420. end
  421. 1 def globus_files_available_here
  422. MsgHelper.t( 'data_set.globus_files_available_here', globus_url: globus_url.to_s )
  423. end
  424. 1 def globus_status_msg( user_email: nil )
  425. msg = if globus_complete?
  426. globus_files_available_here
  427. elsif globus_prepping?
  428. globus_files_prepping_msg( user_email: user_email )
  429. else
  430. globus_file_prep_started_msg( user_email: user_email )
  431. end
  432. msg
  433. end
  434. 1 def show_presenter
  435. Hyrax::DataSetPresenter
  436. end
  437. 1 private
  438. 1 def get_date_uploaded_from_solr(file_set)
  439. field = file_set.solr_document[Solrizer.solr_name('date_uploaded', :stored_sortable, type: :date)]
  440. return if field.blank?
  441. begin
  442. Time.parse(field)
  443. rescue
  444. Rails.logger.info "Unable to parse date: #{field.first.inspect} for #{self['id']}"
  445. end
  446. end
  447. 1 def target_dir_name_id( dir, id, ext = '' )
  448. dir.join "#{DeepBlueDocs::Application.config.base_file_name}#{id}#{ext}"
  449. end
  450. end
  451. end

app/controllers/hyrax/deepblue_controller.rb

100.0% lines covered

16 relevant lines. 16 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'edtf'
  3. 1 module Hyrax
  4. 1 class DeepblueController < ApplicationController
  5. 1 include Hyrax::BreadcrumbsForWorks
  6. 1 def box_enabled?
  7. 1 false
  8. end
  9. 1 def display_provenance_log_enabled?
  10. 1 false
  11. end
  12. 1 def doi_minting_enabled?
  13. 1 false
  14. end
  15. 1 def globus_download_enabled?
  16. 1 false
  17. end
  18. # def mint_doi_enabled?
  19. # false
  20. # end
  21. 1 def tombstone_enabled?
  22. 1 false
  23. end
  24. 1 def zip_download_enabled?
  25. 1 false
  26. end
  27. end
  28. end

app/controllers/hyrax/dissertations_controller.rb

100.0% lines covered

5 relevant lines. 5 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. # Generated controller for Dissertation
  4. 1 class DissertationsController < DeepblueController
  5. # Adds Hyrax behaviors to the controller.
  6. 1 include Hyrax::WorksControllerBehavior
  7. #include Hyrax::BreadcrumbsForWorks
  8. 1 self.curation_concern_type = ::Dissertation
  9. # Use this line if you want to use a custom presenter
  10. 1 self.show_presenter = Hyrax::DissertationPresenter
  11. end
  12. end

app/controllers/hyrax/file_sets_controller.rb

55.17% lines covered

58 relevant lines. 32 lines covered and 26 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require File.join( Gem::Specification.find_by_name("hyrax").full_gem_path, "app/controllers/hyrax/file_sets_controller.rb" )
  3. 1 module Hyrax
  4. # monkey patch FileSetsController
  5. 1 class FileSetsController < ApplicationController
  6. 1 PARAMS_KEY = 'file_set'
  7. 1 self.show_presenter = Hyrax::DsFileSetPresenter
  8. 1 alias_method :monkey_attempt_update, :attempt_update
  9. # alias_method :monkey_update_metadata, :update_metadata
  10. 1 before_action :provenance_log_destroy, only: [:destroy]
  11. 1 before_action :provenance_log_update_before, only: [:update]
  12. 1 after_action :provenance_log_create, only: [:create]
  13. 1 after_action :provenance_log_update_after, only: [:update]
  14. 1 protect_from_forgery with: :null_session, only: [:display_provenance_log]
  15. ## Provenance log
  16. 1 def provenance_log_create
  17. 1 curation_concern.provenance_create( current_user: current_user, event_note: 'FileSetsController' )
  18. end
  19. 1 def provenance_log_destroy
  20. 1 curation_concern.provenance_destroy( current_user: current_user, event_note: 'FileSetsController' )
  21. end
  22. 1 def provenance_log_update_after
  23. 1 curation_concern.provenance_log_update_after( current_user: current_user,
  24. # event_note: 'FileSetsController.provenance_log_update_after',
  25. update_attr_key_values: @update_attr_key_values )
  26. end
  27. 1 def provenance_log_update_before
  28. 1 @update_attr_key_values = curation_concern.provenance_log_update_before( form_params: params[PARAMS_KEY].dup )
  29. end
  30. ## end Provenance log
  31. ## display provenance log
  32. 1 def display_provenance_log
  33. # load provenance log for this work
  34. 1 file_path = Deepblue::ProvenancePath.path_for_reference( curation_concern.id )
  35. 1 Deepblue::LoggingHelper.bold_debug [ "DataSetsController", "display_provenance_log", file_path ]
  36. 1 Deepblue::ProvenanceLogService.entries( curation_concern.id, refresh: true )
  37. # continue on to normal display
  38. 1 redirect_to [main_app, curation_concern]
  39. end
  40. 1 def display_provenance_log_enabled?
  41. 1 true
  42. end
  43. 1 def provenance_log_entries_present?
  44. provenance_log_entries.present?
  45. end
  46. ## end display provenance log
  47. 1 protected
  48. 1 def attempt_update
  49. # Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  50. # Deepblue::LoggingHelper.called_from,
  51. # "current_user=#{current_user}",
  52. # Deepblue::LoggingHelper.obj_class( "actor", actor ) ]
  53. if wants_to_revert?
  54. Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  55. Deepblue::LoggingHelper.called_from,
  56. "current_user=#{current_user}",
  57. Deepblue::LoggingHelper.obj_class( "actor", actor ),
  58. "wants to revert" ]
  59. actor.revert_content(params[:revision])
  60. elsif params.key?(:file_set)
  61. if params[:file_set].key?(:files)
  62. Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  63. Deepblue::LoggingHelper.called_from,
  64. "current_user=#{current_user}",
  65. Deepblue::LoggingHelper.obj_class( "actor", actor ),
  66. "actor.update_content" ]
  67. actor.update_content(params[:file_set][:files].first)
  68. else
  69. Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  70. Deepblue::LoggingHelper.called_from,
  71. "current_user=#{current_user}",
  72. "update_metadata" ]
  73. update_metadata
  74. end
  75. end
  76. end
  77. 1 def presenter
  78. @presenter ||= begin
  79. curation_concern = search_result_document( params )
  80. show_presenter.new( curation_concern, current_ability, request )
  81. end
  82. end
  83. 1 def show_presenter
  84. Hyrax::DsFileSetPresenter
  85. end
  86. 1 def search_result_document( search_params )
  87. _, document_list = search_results( search_params )
  88. return document_list.first unless document_list.empty?
  89. # document_not_found!
  90. raise CanCan::AccessDenied
  91. rescue Blacklight::Exceptions::RecordNotFound => e
  92. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  93. ::Deepblue::LoggingHelper.called_from,
  94. "e=#{e}",
  95. "" ]
  96. begin
  97. # check with Fedora to see if the requested id was deleted
  98. id = params[:id]
  99. ActiveFedora::Base.find( id )
  100. rescue Ldp::Gone => gone
  101. # it was deleted
  102. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  103. ::Deepblue::LoggingHelper.called_from,
  104. "gone=#{gone.class} #{gone.message} at #{gone.backtrace[0]}",
  105. "" ]
  106. # okay, since this looks like a deleted curation concern, we can check the provenance log
  107. # if admin, redirect to the provenance log controller
  108. if current_ability.admin?
  109. url = Rails.application.routes.url_helpers.url_for( only_path: true,
  110. action: 'show',
  111. controller: 'provenance_log',
  112. id: id )
  113. return redirect_to( url, error: "#{id} was deleted." )
  114. end
  115. rescue ActiveFedora::ObjectNotFoundError => e2
  116. # nope, never existed
  117. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  118. ::Deepblue::LoggingHelper.called_from,
  119. "e2=#{e2.class} #{e2.message} at #{e2.backtrace[0]}",
  120. "" ]
  121. end
  122. raise CanCan::AccessDenied
  123. end
  124. end
  125. end

app/controllers/hyrax/generic_works_controller.rb

100.0% lines covered

6 relevant lines. 6 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work GenericWork`
  3. 1 module Hyrax
  4. # Generated controller for GenericWork
  5. 1 class GenericWorksController < ApplicationController
  6. # Adds Hyrax behaviors to the controller.
  7. 1 include Hyrax::WorksControllerBehavior
  8. 1 include Hyrax::BreadcrumbsForWorks
  9. 1 self.curation_concern_type = ::GenericWork
  10. # Use this line if you want to use a custom presenter
  11. 1 self.show_presenter = Hyrax::GenericWorkPresenter
  12. end
  13. end

app/controllers/hyrax/my/collections_controller.rb

48.0% lines covered

75 relevant lines. 36 lines covered and 39 lines missed.
    
  1. 1 module Hyrax
  2. 1 module My
  3. 1 class CollectionsController < MyController
  4. 1 EVENT_NOTE = 'Hyrax::My::CollectionsController'
  5. 1 PARAMS_KEY = 'collection'
  6. # Define collection specific filter facets.
  7. 1 def self.configure_facets
  8. 1 configure_blacklight do |config|
  9. # Name of pivot facet must match field name that uses helper_method
  10. 1 config.add_facet_field Collection.collection_type_gid_document_field_name,
  11. helper_method: :collection_type_label, limit: 5,
  12. pivot: ['has_model_ssim', Collection.collection_type_gid_document_field_name],
  13. label: I18n.t('hyrax.dashboard.my.heading.collection_type')
  14. # This causes AdminSets to also be shown with the Collection Type label
  15. 1 config.add_facet_field 'has_model_ssim',
  16. label: I18n.t('hyrax.dashboard.my.heading.collection_type'),
  17. limit: 5, show: false
  18. end
  19. end
  20. 1 configure_facets
  21. 1 before_action :my_collections_controller_debug_output
  22. 1 before_action :provenance_log_update_before, only: [:update]
  23. 1 before_action :visiblity_changed, only: [:update]
  24. 1 after_action :provenance_log_update_after, only: [:update]
  25. 1 after_action :visibility_changed_update, only: [:update]
  26. 1 protect_from_forgery with: :null_session, only: [:display_provenance_log]
  27. 1 def my_collections_controller_debug_output
  28. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  29. # Deepblue::LoggingHelper.called_from,
  30. # "params=#{params}" ]
  31. end
  32. 1 def curation_concern
  33. @collection ||= ActiveFedora::Base.find(params[:id])
  34. end
  35. ## Provenance log
  36. 1 def provenance_log_update_after
  37. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  38. # Deepblue::LoggingHelper.called_from,
  39. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  40. # "@update_attr_key_values=#{@update_attr_key_values}",
  41. # "" ]
  42. curation_concern.provenance_log_update_after( current_user: current_user,
  43. # event_note: 'CollectionsController.provenance_log_update_after',
  44. update_attr_key_values: @update_attr_key_values )
  45. end
  46. 1 def provenance_log_update_before
  47. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  48. # Deepblue::LoggingHelper.called_from,
  49. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  50. # "" ]
  51. return unless @update_attr_key_values.nil?
  52. @update_attr_key_values = curation_concern.provenance_log_update_before( form_params: params[PARAMS_KEY].dup )
  53. end
  54. ## end Provenance log
  55. ## display provenance log
  56. 1 def display_provenance_log
  57. # load provenance log for this work
  58. id = @collection.id # curation_concern.id
  59. file_path = Deepblue::ProvenancePath.path_for_reference( id )
  60. Deepblue::LoggingHelper.bold_debug [ "CollectionsController", "display_provenance_log", file_path ]
  61. Deepblue::ProvenanceLogService.entries( id, refresh: true )
  62. # continue on to normal display
  63. #redirect_to [main_app, curation_concern]
  64. redirect_back fallback_location: root_url
  65. end
  66. 1 def display_provenance_log_enabled?
  67. true
  68. end
  69. 1 def provenance_log_entries_present?
  70. provenance_log_entries.present?
  71. end
  72. ## end display provenance log
  73. ## visibility / publish
  74. 1 def visiblity_changed
  75. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  76. # Deepblue::LoggingHelper.called_from,
  77. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  78. # "" ]
  79. @update_attr_key_values = curation_concern.provenance_log_update_before( form_params: params[PARAMS_KEY].dup )
  80. if visibility_to_private?
  81. mark_as_set_to_private
  82. elsif visibility_to_public?
  83. mark_as_set_to_public
  84. end
  85. end
  86. 1 def visibility_changed_update
  87. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  88. # Deepblue::LoggingHelper.called_from,
  89. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  90. # "" ]
  91. if curation_concern.private? && @visibility_changed_to_private
  92. workflow_unpublish
  93. elsif curation_concern.public? && @visibility_changed_to_public
  94. workflow_publish
  95. end
  96. end
  97. 1 def visibility_to_private?
  98. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  99. # Deepblue::LoggingHelper.called_from,
  100. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  101. # "" ]
  102. return false if curation_concern.private?
  103. params[PARAMS_KEY]['visibility'] == Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
  104. end
  105. 1 def visibility_to_public?
  106. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  107. # Deepblue::LoggingHelper.called_from,
  108. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  109. # "" ]
  110. return false if curation_concern.public?
  111. params[PARAMS_KEY]['visibility'] == Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
  112. end
  113. 1 def mark_as_set_to_private
  114. @visibility_changed_to_public = false
  115. @visibility_changed_to_private = true
  116. end
  117. 1 def mark_as_set_to_public
  118. @visibility_changed_to_public = true
  119. @visibility_changed_to_private = false
  120. end
  121. ## end visibility / publish
  122. 1 def search_builder_class
  123. Hyrax::My::CollectionsSearchBuilder
  124. end
  125. 1 def index
  126. add_breadcrumb t(:'hyrax.controls.home'), root_path
  127. add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path
  128. add_breadcrumb t(:'hyrax.admin.sidebar.collections'), hyrax.my_collections_path
  129. collection_type_list_presenter
  130. managed_collections_count
  131. super
  132. end
  133. 1 private
  134. 1 def search_action_url(*args)
  135. hyrax.my_collections_url(*args)
  136. end
  137. # The url of the "more" link for additional facet values
  138. 1 def search_facet_path(args = {})
  139. hyrax.my_dashboard_collections_facet_path(args[:id])
  140. end
  141. 1 def collection_type_list_presenter
  142. @collection_type_list_presenter ||= Hyrax::SelectCollectionTypeListPresenter.new(current_user)
  143. end
  144. 1 def managed_collections_count
  145. @managed_collection_count = Hyrax::Collections::ManagedCollectionsService.managed_collections_count(scope: self)
  146. end
  147. end
  148. end
  149. end

app/controllers/robots_controller.rb

92.31% lines covered

26 relevant lines. 24 lines covered and 2 lines missed.
    
  1. 1 class RobotsController < ApplicationController
  2. 1 before_action :authenticate_user!, except: :show
  3. 1 before_action :find_robots_txt
  4. 1 before_action :throw_breadcrumbs, except: :show
  5. 1 layout 'hyrax/dashboard'
  6. 1 def show
  7. 3 render body: @robots_txt.value
  8. end
  9. 1 def edit
  10. 2 authorize! :edit, @robots_txt
  11. end
  12. 1 def update
  13. 2 authorize! :update, @robots_txt
  14. 1 respond_to do |format|
  15. 1 if @robots_txt.update(permitted_params)
  16. 2 format.html { redirect_to edit_robots_path, notice: 'robots.txt updated.' }
  17. else
  18. flash.now[:alert] = "robots.txt could not be updated. #{@robots_txt.errors.full_messages}"
  19. format.html { render :edit }
  20. end
  21. end
  22. end
  23. 1 private
  24. 1 def find_robots_txt
  25. 7 @robots_txt = ContentBlock.find_or_create_by(name: 'robots_txt')
  26. end
  27. 1 def throw_breadcrumbs
  28. 4 add_breadcrumb t(:'hyrax.controls.home'), root_path
  29. 4 add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path
  30. 4 add_breadcrumb t(:'hyrax.admin.sidebar.configuration'), '#'
  31. 4 add_breadcrumb 'robots.txt', edit_robots_path
  32. end
  33. 1 def permitted_params
  34. 1 params.require(:content_block).permit(:value)
  35. end
  36. end

app/forms/deepbluedocs/default_work_form_behavior.rb

76.32% lines covered

38 relevant lines. 29 lines covered and 9 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepbluedocs
  3. 1 module DefaultWorkFormBehavior
  4. 1 extend ActiveSupport::Concern
  5. 1 included do
  6. # include ScholarsArchive::DateTermsBehavior
  7. # include ScholarsArchive::NestedBehavior
  8. # accessor attributes only used to group dates and geo fields and allow proper ordering in this form
  9. 1 attr_accessor :dates_section
  10. 1 attr_accessor :geo_section
  11. 1 attr_accessor :other_affiliation_other
  12. 1 attr_accessor :degree_level_other
  13. 1 attr_accessor :degree_field_other
  14. 1 attr_accessor :degree_name_other
  15. # order isn't significant for self.terms
  16. 1 self.terms += %i[
  17. academic_affiliation
  18. additional_information
  19. alt_title
  20. bibliographic_citation
  21. conference_location
  22. conference_name
  23. conference_section
  24. date_accepted
  25. date_available
  26. date_collected
  27. date_copyright
  28. date_issued
  29. date_modified
  30. date_reviewed
  31. date_uploaded
  32. date_valid
  33. degree_field
  34. degree_level
  35. degree_name
  36. description_abstract
  37. digitization_spec
  38. dspace_collection
  39. dspace_community
  40. embargo_reason
  41. file_extent
  42. file_format
  43. funding_body
  44. funding_statement
  45. hydrologic_unit_code
  46. in_series
  47. isbn
  48. issn
  49. license
  50. peerreviewed
  51. replaces
  52. resource_type
  53. tableofcontents
  54. ]
  55. 1 self.required_fields += [:resource_type]
  56. 1 self.required_fields -= [:keyword]
  57. 1 class_attribute :default_work_primary_terms
  58. # TODO: is order significant self.default_work_primary_terms?
  59. 1 self.default_work_primary_terms =
  60. %i[
  61. title
  62. alt_title
  63. creator
  64. contributor
  65. description_abstract
  66. license
  67. resource_type
  68. identifier
  69. dates_section
  70. degree_level
  71. degree_name
  72. degree_field
  73. bibliographic_citation
  74. academic_affiliation
  75. in_series
  76. subject
  77. tableofcontents
  78. rights_statement
  79. ]
  80. 1 class_attribute :default_work_secondary_terms
  81. # TODO: is order significant self.default_work_secondary_terms?
  82. 1 self.default_work_secondary_terms =
  83. %i[
  84. hydrologic_unit_code
  85. geo_section
  86. funding_statement
  87. publisher
  88. peerreviewed
  89. conference_location
  90. conference_name
  91. conference_section
  92. language
  93. file_format
  94. file_extent
  95. digitization_spec
  96. replaces
  97. additional_information
  98. isbn
  99. issn
  100. ]
  101. 1 def primary_terms
  102. 1 if current_ability.admin?
  103. default_work_primary_terms | super
  104. default_work_primary_terms.delete(:curation_notes_admin)
  105. default_work_primary_terms.delete(:curation_notes_user)
  106. default_work_primary_terms << :curation_notes_admin
  107. default_work_primary_terms << :curation_notes_user
  108. default_work_primary_terms
  109. else
  110. 1 default_work_primary_terms | super
  111. 1 default_work_primary_terms.delete(:curation_notes_admin)
  112. 1 default_work_primary_terms.delete(:curation_notes_user)
  113. 1 default_work_primary_terms
  114. end
  115. end
  116. 1 def secondary_terms
  117. 1 t = default_work_secondary_terms
  118. # jose admin? not found byebug
  119. # t << [:keyword, :source, :funding_body, :dspace_community, :dspace_collection] if current_ability.current_user.admin?
  120. 1 t.flatten
  121. end
  122. 1 def self.date_terms
  123. %i[
  124. date_created
  125. date_available
  126. date_copyright
  127. date_issued
  128. date_collected
  129. date_valid
  130. date_reviewed
  131. date_accepted
  132. ]
  133. end
  134. 1 def date_terms
  135. self.class.date_terms
  136. end
  137. 1 def self.build_permitted_params
  138. super + date_terms + %i[degree_level degree_name degree_field] + [:embargo_reason] + [
  139. {
  140. nested_geo_attributes: %i[id
  141. _destroy
  142. point_lat
  143. point_lon
  144. bbox_lat_north
  145. bbox_lon_west
  146. bbox_lat_south
  147. bbox_lon_east
  148. label
  149. point
  150. bbox],
  151. nested_related_items_attributes: %i[id _destroy label related_url]
  152. }
  153. ] + [
  154. {
  155. other_affiliation_other: [],
  156. degree_field_other: [],
  157. degree_name_other: []
  158. }
  159. ]
  160. end
  161. end
  162. end
  163. end

app/forms/deepbluedocs/dissertation_work_form_behavior.rb

73.91% lines covered

23 relevant lines. 17 lines covered and 6 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepbluedocs
  3. 1 module DissertationWorkFormBehavior
  4. 1 extend ActiveSupport::Concern
  5. 1 included do
  6. # include ScholarsArchive::DateTermsBehavior
  7. # include ScholarsArchive::NestedBehavior
  8. # accessor attributes only used to group dates and geo fields and allow proper ordering in this form
  9. 1 attr_accessor :dates_section
  10. 1 attr_accessor :geo_section
  11. 1 attr_accessor :other_affiliation_other
  12. 1 attr_accessor :degree_level_other
  13. 1 attr_accessor :degree_field_other
  14. 1 attr_accessor :degree_name_other
  15. 1 self.terms += [ :description_thesisdegreediscipline, :date_submitted, :contributor_advisor, :contributor_committeemember, :description_thesisdegreegrantor, :identifier, :identifier_orcid, :type_none, :type_snre, :subject_other, :language_none, :contributor_author, :identifier_uniqname, :description_thesisdegreename, :date_uploaded, :date_modified, :academic_affiliation, :alt_title, :description_abstract, :license, :resource_type, :date_available, :date_copyright, :date_issued, :date_collected, :date_valid, :date_reviewed, :date_accepted, :degree_level, :degree_name, :degree_field, :replaces, :hydrologic_unit_code, :funding_body, :funding_statement, :in_series, :tableofcontents, :bibliographic_citation, :peerreviewed, :additional_information, :digitization_spec, :file_extent, :file_format, :dspace_community, :dspace_collection, :isbn, :issn, :embargo_reason, :conference_location, :conference_name, :conference_section]
  16. 1 self.required_fields += [:resource_type, :identifier_uniqname, :description_thesisdegreename, :description_thesisdegreediscipline, :date_issued, :date_submitted, :contributor_advisor, :contributor_committeemember, :description_abstract, :description_thesisdegreegrantor]
  17. 1 def primary_terms
  18. [:title, :identifier, :creator, :identifier_uniqname, :identifier_orcid, :description_thesisdegreename, :type_snre, :description_thesisdegreediscipline, :date_issued, :date_submitted, :contributor_advisor, :contributor_committeemember, :description_abstract, :keyword, :subject_other, :description_thesisdegreegrantor, :rights_statement]
  19. end
  20. 1 def secondary_terms
  21. t = [:language_none, :date_available]
  22. # jose admin? not found byebug
  23. #t << [:keyword, :source, :funding_body, :dspace_community, :dspace_collection] if current_ability.current_user.admin?
  24. t.flatten
  25. end
  26. 1 def self.date_terms
  27. [
  28. :date_created,
  29. :date_available,
  30. :date_copyright,
  31. :date_issued,
  32. :date_collected,
  33. :date_valid,
  34. :date_reviewed,
  35. :date_accepted,
  36. ]
  37. end
  38. 1 def date_terms
  39. self.class.date_terms
  40. end
  41. 1 def self.build_permitted_params
  42. super + self.date_terms + [:degree_level, :degree_name, :degree_field] + [:embargo_reason] + [
  43. {
  44. :nested_geo_attributes => [:id, :_destroy, :point_lat, :point_lon, :bbox_lat_north, :bbox_lon_west, :bbox_lat_south, :bbox_lon_east, :label, :point, :bbox],
  45. :nested_related_items_attributes => [:id, :_destroy, :label, :related_url]
  46. }
  47. ] + [
  48. {
  49. :other_affiliation_other => [],
  50. :degree_field_other => [],
  51. :degree_name_other => []
  52. }
  53. ]
  54. end
  55. end
  56. end
  57. end

app/forms/deepbluedocs/generic_work_form_behavior.rb

75.0% lines covered

24 relevant lines. 18 lines covered and 6 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepbluedocs
  3. 1 module GenericWorkFormBehavior
  4. 1 extend ActiveSupport::Concern
  5. 1 included do
  6. # include ScholarsArchive::DateTermsBehavior
  7. # include ScholarsArchive::NestedBehavior
  8. # accessor attributes only used to group dates and geo fields and allow proper ordering in this form
  9. 1 attr_accessor :dates_section
  10. 1 attr_accessor :geo_section
  11. 1 attr_accessor :other_affiliation_other
  12. 1 attr_accessor :degree_level_other
  13. 1 attr_accessor :degree_field_other
  14. 1 attr_accessor :degree_name_other
  15. 1 self.terms += [ :description_sponsorship, :description_mapping, :type_none, :identifier_source, :other_affiliation, :identifier_orcid, :contributor_affiliationumcampus, :contributor_author, :relation_ispartofseries, :date_uploaded, :date_modified, :academic_affiliation, :alt_title, :description_abstract, :license, :resource_type, :date_available, :date_copyright, :date_issued, :date_collected, :date_valid, :date_reviewed, :date_accepted, :degree_level, :degree_name, :degree_field, :replaces, :hydrologic_unit_code, :funding_body, :funding_statement, :in_series, :tableofcontents, :bibliographic_citation, :peerreviewed, :additional_information, :digitization_spec, :file_extent, :file_format, :dspace_community, :dspace_collection, :isbn, :issn, :embargo_reason, :conference_location, :conference_name, :conference_section, :language_none, :subject_hlbtoplevel, :subject_hlbsecondlevel, :description_bitstreamurl, :description_provenance]
  16. 1 self.required_fields += [:resource_type, :contributor_affiliationumcampus]
  17. 1 self.required_fields -= [:keyword]
  18. 1 def primary_terms
  19. [:creator, :identifier_orcid, :academic_affiliation, :other_affiliation, :contributor_affiliationumcampus, :title, :alt_title, :date_issued, :identifier_source, :publisher, :peerreviewed, :bibliographic_citation, :relation_ispartofseries, :identifier, :rights_statement]
  20. end
  21. 1 def secondary_terms
  22. t = [:type_none, :language_none, :description_mapping, :subject, :description_abstract, :description_sponsorship, :description]
  23. # jose admin? not found byebug
  24. #t << [:keyword, :source, :funding_body, :dspace_community, :dspace_collection] if current_ability.current_user.admin?
  25. t.flatten
  26. end
  27. 1 def self.date_terms
  28. [
  29. :date_created,
  30. :date_available,
  31. :date_copyright,
  32. :date_issued,
  33. :date_collected,
  34. :date_valid,
  35. :date_reviewed,
  36. :date_accepted,
  37. :date_accessioned,
  38. ]
  39. end
  40. 1 def date_terms
  41. self.class.date_terms
  42. end
  43. 1 def self.build_permitted_params
  44. super + self.date_terms + [:degree_level, :degree_name, :degree_field, :subject_hlbtoplevel, :subject_hlbsecondlevel, :description_bitstreamurl, :description_provenance] + [:embargo_reason] + [
  45. {
  46. :nested_geo_attributes => [:id, :_destroy, :point_lat, :point_lon, :bbox_lat_north, :bbox_lon_west, :bbox_lat_south, :bbox_lon_east, :label, :point, :bbox],
  47. :nested_related_items_attributes => [:id, :_destroy, :label, :related_url]
  48. }
  49. ] + [
  50. {
  51. :other_affiliation_other => [],
  52. :degree_field_other => [],
  53. :degree_name_other => []
  54. }
  55. ]
  56. end
  57. end
  58. end
  59. end

app/forms/hyrax/data_set_form.rb

100.0% lines covered

12 relevant lines. 12 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 class DataSetForm < DeepblueForm
  4. 1 self.model_class = ::DataSet
  5. 1 self.terms -= %i[ rights_statement ]
  6. 1 self.terms +=
  7. %i[
  8. authoremail
  9. date_coverage
  10. description
  11. resource_type
  12. publisher
  13. fundedby
  14. fundedby_other
  15. doi
  16. description_abstract
  17. keyword
  18. methodology
  19. referenced_by
  20. rights_license
  21. rights_license_other
  22. license_other
  23. curation_notes_admin
  24. curation_notes_user
  25. geo_location_place
  26. geo_location_box
  27. ]
  28. 1 self.default_work_primary_terms =
  29. %i[
  30. title
  31. creator
  32. authoremail
  33. methodology
  34. resource_type
  35. description_abstract
  36. description
  37. publisher
  38. date_coverage
  39. rights_license
  40. rights_license_other
  41. license_other
  42. fundedby
  43. fundedby_other
  44. keyword
  45. language
  46. referenced_by
  47. curation_notes_admin
  48. curation_notes_user
  49. geo_location_place
  50. geo_location_box
  51. ]
  52. 1 self.default_work_secondary_terms = []
  53. 1 self.required_fields =
  54. %i[
  55. title
  56. creator
  57. authoremail
  58. methodology
  59. description
  60. rights_license
  61. resource_type
  62. description_abstract
  63. publisher
  64. ]
  65. 1 def data_set?
  66. 1 true
  67. end
  68. 1 def merge_date_coverage_attributes!(hsh)
  69. 2 @attributes.merge!(hsh&.stringify_keys || {})
  70. end
  71. end
  72. end

app/forms/hyrax/deepblue_form.rb

66.67% lines covered

9 relevant lines. 6 lines covered and 3 lines missed.
    
  1. # frozen_string_literal: truez
  2. 1 module Hyrax
  3. 1 class DeepblueForm < Hyrax::Forms::WorkForm
  4. 1 include Deepbluedocs::DefaultWorkFormBehavior
  5. 1 def data_set?
  6. false
  7. end
  8. 1 def dissertation?
  9. false
  10. end
  11. 1 def generic_work?
  12. false
  13. end
  14. end
  15. end

app/forms/hyrax/dissertation_form.rb

100.0% lines covered

5 relevant lines. 5 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. # Generated form for Dissertation
  4. 1 class DissertationForm < DeepblueForm
  5. 1 include Deepbluedocs::DissertationWorkFormBehavior
  6. 1 self.model_class = ::Dissertation
  7. 1 self.terms += [:resource_type]
  8. end
  9. end

app/forms/hyrax/forms/collection_form.rb

55.22% lines covered

67 relevant lines. 37 lines covered and 30 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 module Forms
  4. 1 class CollectionForm
  5. 1 include HydraEditor::Form
  6. 1 include HydraEditor::Form::Permissions
  7. 1 include ::Hyrax::BrandingHelper
  8. # Used by the search builder
  9. 1 attr_reader :scope
  10. 1 delegate :id, :depositor, :permissions, :human_readable_type, :member_ids, :nestable?, to: :model
  11. 1 class_attribute :membership_service_class, :default_work_primary_terms, :default_work_secondary_terms
  12. # Required for search builder (FIXME)
  13. 1 alias collection model
  14. 1 self.model_class = ::Collection
  15. 1 self.membership_service_class = Collections::CollectionMemberService
  16. 1 delegate :blacklight_config, to: Hyrax::CollectionsController
  17. 1 self.terms = %i[
  18. authoremail
  19. based_near
  20. collection_type_gid
  21. contributor
  22. creator
  23. date_coverage
  24. date_created
  25. description
  26. fundedby
  27. grantnumber
  28. identifier
  29. keyword
  30. language
  31. license
  32. methodology
  33. publisher
  34. referenced_by
  35. related_url
  36. representative_id
  37. resource_type
  38. rights_license
  39. subject
  40. subject_discipline
  41. thumbnail_id
  42. title
  43. visibility
  44. ]
  45. 1 self.default_work_primary_terms =
  46. %i[
  47. title
  48. creator
  49. description
  50. keyword
  51. subject_discipline
  52. language
  53. referenced_by
  54. ]
  55. 1 self.default_work_secondary_terms = []
  56. 1 self.required_fields = %i[
  57. title
  58. creator
  59. description
  60. subject_discipline
  61. ]
  62. 1 ProxyScope = Struct.new(:current_ability, :repository, :blacklight_config) do
  63. 1 def can?(*args)
  64. current_ability.can?(*args)
  65. end
  66. end
  67. # @param model [Collection] the collection model that backs this form
  68. # @param current_ability [Ability] the capabilities of the current user
  69. # @param repository [Blacklight::Solr::Repository] the solr repository
  70. 1 def initialize(model, current_ability, repository)
  71. super(model)
  72. @scope = ProxyScope.new(current_ability, repository, blacklight_config)
  73. end
  74. 1 def permission_template
  75. @permission_template ||= begin
  76. template_model = PermissionTemplate.find_or_create_by(source_id: model.id)
  77. PermissionTemplateForm.new(template_model)
  78. end
  79. end
  80. # @return [Hash] All FileSets in the collection, file.to_s is the key, file.id is the value
  81. 1 def select_files
  82. Hash[all_files_with_access]
  83. end
  84. # Terms that appear above the accordion
  85. 1 def primary_terms
  86. default_work_primary_terms
  87. end
  88. # Terms that appear within the accordion
  89. 1 def secondary_terms
  90. default_work_secondary_terms
  91. end
  92. 1 def relative_url_root
  93. rv = ::DeepBlueDocs::Application.config.relative_url_root
  94. return rv if rv
  95. ''
  96. end
  97. 1 def banner_info
  98. @banner_info ||= branding_banner_info( id: id )
  99. end
  100. 1 def logo_info
  101. @logo_info ||= branding_logo_info( id: id )
  102. end
  103. # Do not display additional fields if there are no secondary terms
  104. # @return [Boolean] display additional fields on the form?
  105. 1 def display_additional_fields?
  106. secondary_terms.any?
  107. end
  108. 1 def thumbnail_title
  109. return unless model.thumbnail
  110. model.thumbnail.title.first
  111. end
  112. 1 def list_parent_collections
  113. collection.member_of_collections
  114. end
  115. 1 def list_child_collections
  116. collection_member_service.available_member_subcollections.documents
  117. end
  118. 1 def available_parent_collections(scope:)
  119. return @available_parents if @available_parents.present?
  120. collection = Collection.find(id)
  121. colls = Hyrax::Collections::NestedCollectionQueryService.available_parent_collections(child: collection, scope: scope, limit_to_id: nil)
  122. @available_parents = colls.map do |col|
  123. { "id" => col.id, "title_first" => col.title.first }
  124. end
  125. @available_parents.to_json
  126. end
  127. 1 private
  128. 1 def all_files_with_access
  129. member_presenters(member_work_ids).flat_map(&:file_set_presenters).map { |x| [x.to_s, x.id] }
  130. end
  131. # Override this method if you have a different way of getting the member's ids
  132. 1 def member_work_ids
  133. response = collection_member_service.available_member_work_ids.response
  134. response.fetch('docs').map { |doc| doc['id'] }
  135. end
  136. 1 def collection_member_service
  137. @collection_member_service ||= membership_service_class.new(scope: scope, collection: collection, params: blacklight_config.default_solr_params)
  138. end
  139. 1 def member_presenters(member_ids)
  140. PresenterFactory.build_for(ids: member_ids,
  141. presenter_class: WorkShowPresenter,
  142. presenter_args: [nil])
  143. end
  144. end
  145. end
  146. end

app/forms/hyrax/generic_work_form.rb

100.0% lines covered

5 relevant lines. 5 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work GenericWork`
  3. 1 module Hyrax
  4. # Generated form for GenericWork
  5. 1 class GenericWorkForm < Hyrax::Forms::WorkForm
  6. 1 include Deepbluedocs::GenericWorkFormBehavior
  7. 1 self.model_class = ::GenericWork
  8. 1 self.terms += [:resource_type]
  9. end
  10. end

app/helpers/application_helper.rb

100.0% lines covered

1 relevant lines. 1 lines covered and 0 lines missed.
    
  1. 1 module ApplicationHelper
  2. end

app/helpers/deepblue/email_helper.rb

29.31% lines covered

58 relevant lines. 17 lines covered and 41 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 module EmailHelper
  4. 1 extend ActionView::Helpers::TranslationHelper
  5. 1 def self.contact_email
  6. Settings.hyrax.contact_email
  7. end
  8. 1 def self.curation_concern_url( curation_concern: )
  9. if curation_concern.is_a?( DataSet )
  10. data_set_url( id: curation_concern.id )
  11. elsif curation_concern.is_a?( FileSet )
  12. file_set_url( id: curation_concern.id )
  13. elsif curation_concern.is_a?( Collection )
  14. collection_url( id: curation_concern.id )
  15. else
  16. ""
  17. end
  18. end
  19. 1 def self.collection_url( id: nil, collection: nil )
  20. id = collection.id if collection.present?
  21. host = hostname
  22. Rails.application.routes.url_helpers.hyrax_collection_url( id: id, host: host, only_path: false )
  23. end
  24. 1 def self.data_set_url( id: nil, data_set: nil )
  25. id = data_set.id if data_set.present?
  26. host = hostname
  27. Rails.application.routes.url_helpers.hyrax_data_set_url( id: id, host: host, only_path: false )
  28. end
  29. 1 def self.file_set_url( id: nil, file_set: nil )
  30. id = file_set.id if file_set.present?
  31. host = hostname
  32. Rails.application.routes.url_helpers.hyrax_file_set_url( id: id, host: host, only_path: false )
  33. end
  34. 1 def self.echo_to_rails_logger
  35. DeepBlueDocs::Application.config.email_log_echo_to_rails_logger
  36. end
  37. 1 def self.hostname
  38. rv = Settings.hostname
  39. return rv unless rv.nil?
  40. # then we are in development mode
  41. "http://localhost:3000/#{Settings.relative_url_root}/"
  42. end
  43. 1 def self.log( class_name: 'UnknownClass',
  44. event: 'unknown',
  45. event_note: '',
  46. id: 'unknown_id',
  47. timestamp: LoggingHelper.timestamp_now,
  48. to:,
  49. to_note: '',
  50. from:,
  51. subject:,
  52. message: '',
  53. **key_values )
  54. email_enabled = DeepBlueDocs::Application.config.email_enabled
  55. added_key_values = if to_note.blank?
  56. { to: to, from: from, subject: subject, message: message, email_enabled: email_enabled }
  57. else
  58. { to: to, to_note: to_note, from: from, subject: subject, message: message, email_enabled: email_enabled }
  59. end
  60. key_values.merge! added_key_values
  61. LoggingHelper.log( class_name: class_name,
  62. event: event,
  63. event_note: event_note,
  64. id: id,
  65. timestamp: timestamp,
  66. echo_to_rails_logger: EmailHelper.echo_to_rails_logger,
  67. logger: EMAIL_LOGGER,
  68. **key_values )
  69. end
  70. 1 def self.log_raw( msg )
  71. EMAIL_LOGGER.info( msg )
  72. end
  73. 1 def self.notification_email
  74. 1 Rails.configuration.notification_email
  75. end
  76. 1 def self.send_email( to:, from:, subject:, body:, log: false )
  77. email_enabled = DeepBlueDocs::Application.config.email_enabled
  78. is_enabled = email_enabled ? "is enabled" : "is not enabled"
  79. LoggingHelper.bold_debug [ "EmailHelper.send_email #{is_enabled}", "to: #{to} from: #{from} subject: #{subject}\nbody:\n#{body}" ] if log
  80. return if to.blank?
  81. return unless email_enabled
  82. email = DeepblueMailer.send_an_email( to: to, from: from, subject: subject, body: body )
  83. email.deliver_now
  84. end
  85. 1 def self.user_email
  86. Rails.configuration.user_email
  87. end
  88. 1 def self.user_email_from( current_user, user_signed_in: true )
  89. return nil unless user_signed_in
  90. user_email = nil
  91. unless current_user.nil?
  92. # LoggingHelper.debug "current_user=#{current_user}"
  93. # LoggingHelper.debug "current_user.name=#{current_user.name}"
  94. # LoggingHelper.debug "current_user.email=#{current_user.email}"
  95. user_email = current_user.email
  96. end
  97. user_email
  98. end
  99. end
  100. end

app/helpers/deepblue/event_helper.rb

80.0% lines covered

25 relevant lines. 20 lines covered and 5 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 module EventHelper
  4. 1 def self.after_batch_create_failure_callback( user: )
  5. 1 LoggingCallback.process_event_user( event_name: :after_batch_create_failure, user: user )
  6. end
  7. 1 def self.after_batch_create_success_callback( user: )
  8. 1 LoggingCallback.process_event_user( event_name: :after_batch_create_success, user: user )
  9. end
  10. 1 def self.after_create_concern_callback( curation_concern:, user: )
  11. 2 LoggingCallback.process_event_curation_concern( event_name: :after_create_concern,
  12. curation_concern: curation_concern,
  13. user: user )
  14. 2 return unless curation_concern.respond_to? :provenance_create
  15. 1 curation_concern.provenance_create( current_user: user, event_note: 'after_create_concern' )
  16. end
  17. 1 def self.after_create_fileset_callback( file_set:, user: )
  18. 2 LoggingCallback.process_event_file_set( event_name: :after_create_fileset, file_set: file_set, user: user )
  19. 2 return unless file_set.respond_to? :provenance_create
  20. 1 file_set.provenance_create( current_user: user, event_note: 'after_create_fileset' )
  21. end
  22. 1 def self.after_destroy_callback( id:, user: )
  23. LoggingCallback.process_event_user( event_name: :after_destroy, user: user, msg: "id: #{id}" )
  24. end
  25. 1 def self.after_fixity_check_failure_callback( file_set:, checksum_audit_log: )
  26. LoggingCallback.process_event( event_name: :after_fixity_check_failure,
  27. msg: "file_set: #{file_set} checksum_audit_log: #{checksum_audit_log}" )
  28. end
  29. 1 def self.after_import_url_failure_callback( file_set:, user: )
  30. LoggingCallback.process_event_file_set( event_name: :after_import_url_failure, file_set: file_set, user: user )
  31. end
  32. 1 def self.after_revert_content_callback( file_set:, user: )
  33. LoggingCallback.process_event_file_set( event_name: :after_revert_content, file_set: file_set, user: user )
  34. end
  35. # :after_update_content callback replaced by after_perform block in IngestJob
  36. 1 def self.after_update_content
  37. # TODO
  38. end
  39. 1 def self.after_update_metadata_callback( curation_concern:, user: )
  40. LoggingCallback.process_event_curation_concern( event_name: :after_update_metadata,
  41. curation_concern: curation_concern,
  42. user: user )
  43. # return unless curation_concern.respond_to? :provenance_log_update_after
  44. # curation_concern.provenance_log_update_after( current_user: user, event_note: 'after_update_metadata' )
  45. end
  46. end
  47. end

app/helpers/deepblue/export_files_helper.rb

12.0% lines covered

50 relevant lines. 6 lines covered and 44 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 module ExportFilesHelper
  4. 1 require 'down'
  5. 1 def self.export_file_uri( source_uri:, target_file: )
  6. if source_uri.starts_with?( "http:" ) || source_uri.starts_with?( "https:" )
  7. begin
  8. # see: https://github.com/janko-m/down
  9. Down.download( source_uri, destination: target_file )
  10. bytes_exported = File.size target_file
  11. rescue Exception => e # rubocop:disable Lint/RescueException
  12. Rails.logger.error "ExportFilesHelper.export_file_uri(#{source_uri},#{target_file}) #{e.class}: #{e.message} at #{e.backtrace[0]}"
  13. bytes_exported = open( source_uri ) { |io| IO.copy_stream( io, target_file ) }
  14. end
  15. else
  16. bytes_exported = open( source_uri ) { |io| IO.copy_stream( io, target_file ) }
  17. end
  18. return bytes_exported
  19. end
  20. 1 def self.export_file_uri_bytes( source_uri: )
  21. # TODO: replace this with Down gem
  22. bytes_expected = -1
  23. open( source_uri ) { |io| bytes_expected = io.meta['content-length'] }
  24. return bytes_expected
  25. end
  26. 1 def self.export_file_sets( target_dir:,
  27. file_sets:,
  28. log_prefix: "export_file_sets",
  29. do_export_predicate: ->(_target_file_name, _target_file) { true },
  30. quiet: false,
  31. &on_export_block )
  32. LoggingHelper.debug "#{log_prefix} Starting export to #{target_dir}" unless quiet
  33. files_extracted = {}
  34. total_bytes = 0
  35. file_sets.each do |file_set|
  36. file = file_set.files_to_file
  37. if file.nil?
  38. Rails.logger.warn "#{log_prefix} file_set.id #{file_set.id} files[0] is nil"
  39. elsif file_set.archive_file?
  40. # exclude from .zip
  41. else
  42. target_file_name = file_set.label
  43. # fix possible issues with target file name
  44. target_file_name = '_nil_' if target_file_name.nil?
  45. target_file_name = '_empty_' if target_file_name.empty?
  46. if files_extracted.key? target_file_name
  47. dup_count = 1
  48. base_ext = File.extname target_file_name
  49. base_target_file_name = File.basename target_file_name, base_ext
  50. target_file_name = base_target_file_name + "_" + dup_count.to_s.rjust( 3, '0' ) + base_ext
  51. while files_extracted.key? target_file_name
  52. dup_count += 1
  53. target_file_name = base_target_file_name + "_" + dup_count.to_s.rjust( 3, '0' ) + base_ext
  54. end
  55. end
  56. files_extracted.store( target_file_name, true )
  57. target_file = target_dir.join target_file_name
  58. if do_export_predicate.call( target_file_name, target_file )
  59. source_uri = file.uri.value
  60. # LoggingHelper.debug "#{log_prefix} #{source_uri} exists? #{File.exist?( source_uri )}" unless quiet
  61. LoggingHelper.debug "#{log_prefix} export #{target_file} << #{source_uri}" unless quiet
  62. bytes_copied = export_file_uri( source_uri: source_uri, target_file: target_file )
  63. total_bytes += bytes_copied
  64. copied = DeepblueHelper.human_readable_size( bytes_copied )
  65. LoggingHelper.debug "#{log_prefix} copied #{copied} to #{target_file}" unless quiet
  66. on_export_block.call( target_file_name, target_file ) if on_export_block # rubocop:disable Style/SafeNavigation
  67. else
  68. LoggingHelper.debug "#{log_prefix} skipped export of #{target_file}" unless quiet
  69. end
  70. end
  71. end
  72. total_copied = DeepblueHelper.human_readable_size( total_bytes )
  73. LoggingHelper.debug "#{log_prefix} Finished export to #{target_dir}; total #{total_copied} in #{files_extracted.size} files" unless quiet
  74. total_bytes
  75. end
  76. end
  77. end

app/helpers/deepblue/ingest_helper.rb

13.27% lines covered

113 relevant lines. 15 lines covered and 98 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 module IngestHelper
  4. 1 INGEST_HELPER_VERBOSE = true
  5. # @param [FileSet] file_set
  6. # @param [String] repository_file_id identifier for a Hydra::PCDM::File
  7. # @param [String, NilClass] file_path the cached file within the Hyrax.config.working_path
  8. 1 def self.characterize( file_set,
  9. repository_file_id,
  10. file_path = nil,
  11. continue_job_chain: true,
  12. continue_job_chain_later: true,
  13. current_user: IngestHelper.current_user,
  14. delete_input_file: true,
  15. uploaded_file_ids: [],
  16. **added_prov_key_values )
  17. Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  18. Deepblue::LoggingHelper.called_from,
  19. "file_set=#{file_set}",
  20. "repository_file_id=#{repository_file_id}",
  21. "file_path=#{file_path}",
  22. "continue_job_chain=#{continue_job_chain}",
  23. "continue_job_chain_later=#{continue_job_chain_later}",
  24. "current_user=#{current_user}",
  25. "delete_input_file=#{delete_input_file}",
  26. "uploaded_file_ids=#{uploaded_file_ids}",
  27. "added_prov_key_values=#{added_prov_key_values}",
  28. # "wrapper.methods=#{wrapper.methods.sort}",
  29. "" ] if INGEST_HELPER_VERBOSE
  30. # See Hyrax gem: app/job/characterize_job.rb
  31. file_name = Hyrax::WorkingDirectory.find_or_retrieve( repository_file_id, file_set.id, file_path )
  32. # file_ext = File.extname file_set.label
  33. # if DeepBlueDocs::Application.config.characterize_excluded_ext_set.key? file_ext
  34. # Rails.logger.info "Skipping characterization of file with extension #{file_ext}: #{file_name}"
  35. # file_set.provenance_characterize( current_user: current_user,
  36. # event_note: "skipped_extension(#{file_ext})",
  37. # calling_class: name,
  38. # **added_prov_key_values )
  39. # perform_create_derivatives_job( file_set,
  40. # repository_file_id,
  41. # file_name,
  42. # file_path,
  43. # delete_input_file: delete_input_file,
  44. # continue_job_chain: continue_job_chain,
  45. # continue_job_chain_later: continue_job_chain_later,
  46. # current_user: current_user,
  47. # **added_prov_key_values )
  48. # return
  49. # end
  50. unless file_set.characterization_proxy?
  51. error_msg = "#{file_set.class.characterization_proxy} was not found"
  52. Rails.logger.error error_msg
  53. raise LoadError, error_msg
  54. end
  55. begin
  56. proxy = file_set.characterization_proxy
  57. Hydra::Works::CharacterizationService.run( proxy, file_name )
  58. Rails.logger.debug "Ran characterization on #{proxy.id} (#{proxy.mime_type})"
  59. file_set.provenance_characterize( current_user: current_user,
  60. calling_class: name,
  61. **added_prov_key_values )
  62. file_set.characterization_proxy.save!
  63. file_set.update_index
  64. file_set.parent&.in_collections&.each(&:update_index)
  65. # file_set.parent.in_collections.each( &:update_index ) if file_set.parent
  66. rescue Exception => e # rubocop:disable Lint/RescueException
  67. Rails.logger.error "IngestHelper.create_derivatives(#{file_name}) #{e.class}: #{e.message} at #{e.backtrace[0]}"
  68. ensure
  69. update_total_file_size( file_set, log_prefix: "CharacterizationHelper.characterize()" )
  70. perform_create_derivatives_job( file_set,
  71. repository_file_id,
  72. file_name,
  73. file_path,
  74. continue_job_chain: continue_job_chain,
  75. continue_job_chain_later: continue_job_chain_later,
  76. current_user: current_user,
  77. delete_input_file: delete_input_file,
  78. uploaded_file_ids: uploaded_file_ids,
  79. **added_prov_key_values )
  80. end
  81. end
  82. # @param [FileSet] file_set
  83. # @param [String] repository_file_id identifier for a Hydra::PCDM::File
  84. # @param [String, NilClass] file_path the cached file within the Hyrax.config.working_path
  85. 1 def self.create_derivatives( file_set,
  86. repository_file_id,
  87. file_path = nil,
  88. current_user: IngestHelper.current_user,
  89. delete_input_file: true,
  90. uploaded_file_ids: [],
  91. **added_prov_key_values )
  92. Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  93. Deepblue::LoggingHelper.called_from,
  94. "file_set=#{file_set}",
  95. "repository_file_id=#{repository_file_id}",
  96. "file_path=#{file_path}",
  97. "current_user=#{current_user}",
  98. "delete_input_file=#{delete_input_file}",
  99. "uploaded_file_ids=#{uploaded_file_ids}",
  100. "added_prov_key_values=#{added_prov_key_values}",
  101. # "wrapper.methods=#{wrapper.methods.sort}",
  102. "" ] if INGEST_HELPER_VERBOSE
  103. # See Hyrax gem: app/job/create_derivatives_job.rb
  104. file_name = Hyrax::WorkingDirectory.find_or_retrieve( repository_file_id, file_set.id, file_path )
  105. Rails.logger.warn "Create derivatives for: #{file_name}."
  106. begin
  107. file_ext = File.extname file_set.label
  108. if DeepBlueDocs::Application.config.derivative_excluded_ext_set.key? file_ext
  109. Rails.logger.info "Skipping derivative of file with extension #{file_ext}: #{file_name}"
  110. file_set.provenance_create_derivative( current_user: current_user,
  111. event_note: "skipped_extension #{file_ext}",
  112. calling_class: name,
  113. **added_prov_key_values )
  114. return
  115. end
  116. if file_set.video? && !Hyrax.config.enable_ffmpeg
  117. Rails.logger.info "Skipping video derivative job for file: #{file_name}"
  118. file_set.provenance_create_derivative( current_user: current_user,
  119. event_note: "skipped_extension #{file_ext}",
  120. calling_class: name,
  121. **added_prov_key_values )
  122. return
  123. end
  124. threshold_file_size = DeepBlueDocs::Application.config.derivative_max_file_size
  125. if threshold_file_size > -1 && File.exist?(file_name) && File.size(file_name) > threshold_file_size
  126. human_readable = ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert( threshold_file_size, precision: 3 )
  127. Rails.logger.info "Skipping file larger than #{human_readable} for create derivative job file: #{file_name}"
  128. file_set.provenance_create_derivative( current_user: current_user,
  129. event_note: "skipped_file_size #{File.size(file_name)}",
  130. calling_class: name,
  131. **added_prov_key_values )
  132. return
  133. end
  134. Rails.logger.debug "About to call create derivatives: #{file_name}."
  135. file_set.create_derivatives( file_name )
  136. Rails.logger.debug "Create derivatives successful: #{file_name}."
  137. file_set.provenance_create_derivative( current_user: current_user,
  138. calling_class: name,
  139. **added_prov_key_values )
  140. # Reload from Fedora and reindex for thumbnail and extracted text
  141. file_set.reload
  142. file_set.update_index
  143. file_set.parent.update_index if parent_needs_reindex?(file_set)
  144. Rails.logger.debug "Successful create derivative job for file: #{file_name}"
  145. rescue Exception => e # rubocop:disable Lint/RescueException
  146. Rails.logger.error "IngestHelper.create_derivatives(#{file_set},#{repository_file_id},#{file_path}) #{e.class}: #{e.message} at #{e.backtrace[0]}"
  147. ensure
  148. # This is the last step in the process ( ingest job -> characterization job -> create derivative (last step))
  149. # So now it's safe to remove the file uploaded file.
  150. delete_file( file_path, delete_file_flag: delete_input_file, msg_prefix: 'Create derivatives ' )
  151. end
  152. end
  153. 1 def self.current_user
  154. ProvenanceHelper.system_as_current_user
  155. end
  156. 1 def self.delete_file( file_path, delete_file_flag: false, msg_prefix: '' )
  157. return unless delete_file_flag
  158. return unless File.exist? file_path
  159. File.delete file_path
  160. Rails.logger.debug "#{msg_prefix}file deleted: #{file_path}"
  161. end
  162. # @param [FileSet] file_set
  163. # @param [String] filepath the cached file within the Hyrax.config.working_path
  164. # @param [User] user
  165. # @option opts [String] mime_type
  166. # @option opts [String] filename
  167. # @option opts [String] relation, ex. :original_file
  168. 1 def self.ingest( file_set, path, _user, uploaded_file_ids = [], opts = {} )
  169. Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  170. Deepblue::LoggingHelper.called_from,
  171. "file_set=#{file_set}",
  172. "path=#{path}",
  173. "uploaded_file_ids=#{uploaded_file_ids}",
  174. "user=#{_user}",
  175. "opts=#{opts}",
  176. # "wrapper.methods=#{wrapper.methods.sort}",
  177. "" ] if INGEST_HELPER_VERBOSE
  178. # launched from Hyrax gem: app/actors/hyrax/actors/file_set_actor.rb FileSetActor#create_content
  179. # See Hyrax gem: app/job/ingest_local_file_job.rb
  180. # def perform(file_set, path, user)
  181. file_set.label ||= File.basename(path)
  182. file_set_actor_create_content( file_set, File.open(path), uploaded_file_ids: uploaded_file_ids, bypass_fedora: opts[:bypass_fedora])
  183. end
  184. 1 def self.file_set_actor_create_content( file_set, file, relation = :original_file, uploaded_file_ids: [], bypass_fedora: false )
  185. # If the file set doesn't have a title or label assigned, set a default.
  186. file_set.label ||= label_for( file )
  187. file_set.title = [file_set.label] if file_set.title.blank?
  188. return false unless file_set.save # Need to save to get an id
  189. if bypass_fedora
  190. Hydra::Works::AddExternalFileToFileSet.call( file_set,
  191. bypass_fedora,
  192. relation,
  193. versioning: false )
  194. return false unless file_set.save
  195. repository_file = related_file( file_set, relation )
  196. Hyrax::VersioningService.create( repository_file, user )
  197. else
  198. # if from_url
  199. # # If ingesting from URL, don't spawn an IngestJob; instead
  200. # # reach into the FileActor and run the ingest with the file instance in
  201. # # hand. Do this because we don't have the underlying UploadedFile instance
  202. # file_actor = build_file_actor(relation)
  203. # file_actor.ingest_file(wrapper!(file: file, relation: relation))
  204. # # Copy visibility and permissions from parent (work) to
  205. # # FileSets even if they come in from BrowseEverything
  206. # VisibilityCopyJob.perform_later(file_set.parent)
  207. # InheritPermissionsJob.perform_later(file_set.parent)
  208. # else
  209. # IngestJob.perform_later(wrapper!(file: file, relation: relation))
  210. # end
  211. io = JobIoWrapper.create_with_varied_file_handling!( user: user, file: file, relation: relation, file_set: file_set )
  212. # FileActor#ingest_file(io)
  213. # def ingest_file(io)
  214. # Skip versioning because versions will be minted by VersionCommitter as necessary during save_characterize_and_record_committer.
  215. Hydra::Works::AddFileToFileSet.call( file_set,
  216. io,
  217. relation,
  218. versioning: false )
  219. return false unless file_set.save
  220. repository_file = related_file( file_set, relation )
  221. Hyrax::VersioningService.create( repository_file, user )
  222. virus_scan( file_set )
  223. # pathhint = io.uploaded_file.uploader.path if io.uploaded_file # in case next worker is on same filesystem
  224. # CharacterizeJob.perform_later(file_set, repository_file.id, pathhint || io.path)
  225. characterize( file_set, repository_file.id, io.path )
  226. end
  227. end
  228. # For the label, use the original_filename or original_name if it's there.
  229. # If the file was imported via URL, parse the original filename.
  230. # If all else fails, use the basename of the file where it sits.
  231. # @note This is only useful for labeling the file_set, because of the recourse to import_url
  232. 1 def self.label_for( file )
  233. if file.is_a?(Hyrax::UploadedFile) # filename not present for uncached remote file!
  234. file.uploader.filename.present? ? file.uploader.filename : File.basename(Addressable::URI.parse(file.file_url).path)
  235. elsif file.respond_to?(:original_name) # e.g. Hydra::Derivatives::IoDecorator
  236. file.original_name
  237. elsif file_set.import_url.present?
  238. # This path is taken when file is a Tempfile (e.g. from ImportUrlJob)
  239. File.basename(Addressable::URI.parse(file_set.import_url).path)
  240. else
  241. File.basename(file)
  242. end
  243. end
  244. 1 def self.related_file( file_set, relation )
  245. file_set.public_send(relation) || raise("No #{relation} returned for FileSet #{file_set.id}")
  246. end
  247. # If this file_set is the thumbnail for the parent work,
  248. # then the parent also needs to be reindexed.
  249. 1 def self.parent_needs_reindex?(file_set)
  250. return false unless file_set.parent
  251. file_set.parent.thumbnail_id == file_set.id
  252. end
  253. 1 def self.perform_create_derivatives_job( file_set,
  254. repository_file_id,
  255. file_name,
  256. file_path,
  257. continue_job_chain: true,
  258. continue_job_chain_later: true,
  259. current_user: IngestHelper.current_user,
  260. delete_input_file: true,
  261. uploaded_file_ids: [],
  262. **added_prov_key_values )
  263. Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  264. Deepblue::LoggingHelper.called_from,
  265. "file_set=#{file_set}",
  266. "repository_file_id=#{repository_file_id}",
  267. "file_name=#{file_name}",
  268. "file_path=#{file_path}",
  269. "continue_job_chain=#{continue_job_chain}",
  270. "continue_job_chain_later=#{continue_job_chain_later}",
  271. "current_user=#{current_user}",
  272. "delete_input_file=#{delete_input_file}",
  273. "uploaded_file_ids=#{uploaded_file_ids}",
  274. "added_prov_key_values=#{added_prov_key_values}",
  275. # "wrapper.methods=#{wrapper.methods.sort}",
  276. "" ] if INGEST_HELPER_VERBOSE
  277. if continue_job_chain
  278. if continue_job_chain_later
  279. # TODO: see about adding **added_prov_key_values to this:
  280. CreateDerivativesJob.perform_later( file_set,
  281. repository_file_id,
  282. file_name,
  283. current_user: current_user,
  284. delete_input_file: delete_input_file,
  285. uploaded_file_ids: uploaded_file_ids )
  286. else
  287. # CreateDerivativesJob.perform_now( file_set,
  288. # repository_file_id,
  289. # file_name,
  290. # current_user: current_user,
  291. # delete_input_file: delete_input_file,
  292. # uploaded_file_ids: uploaded_file_ids )
  293. create_derivatives( file_set,
  294. repository_file_id,
  295. file_name,
  296. delete_input_file: delete_input_file,
  297. current_user: current_user,
  298. uploaded_file_ids: uploaded_file_ids,
  299. **added_prov_key_values )
  300. end
  301. else
  302. delete_file( file_path, delete_file_flag: delete_input_file, msg_prefix: 'Characterize ' )
  303. end
  304. end
  305. 1 def self.update_total_file_size( file_set, log_prefix: nil )
  306. Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  307. Deepblue::LoggingHelper.called_from,
  308. "file_set=#{file_set}",
  309. "log_prefix=#{log_prefix}",
  310. # "wrapper.methods=#{wrapper.methods.sort}",
  311. "" ] if INGEST_HELPER_VERBOSE
  312. # Rails.logger.info "begin IngestHelper.update_total_file_size"
  313. # Rails.logger.debug "#{log_prefix} file_set.orginal_file.size=#{file_set.original_file.size}" unless log_prefix.nil?
  314. # Rails.logger.info "nothing to update, parent is nil" if file_set.parent.nil?
  315. return if file_set.parent.nil?
  316. total = file_set.parent.total_file_size
  317. if total.nil? || total.zero?
  318. Rails.logger.debug "#{log_prefix}.file_set.parent.update_total_file_size!" unless log_prefix.nil?
  319. file_set.parent.update_total_file_size!
  320. else
  321. Rails.logger.debug "#{log_prefix}.file_set.parent.total_file_size_add_file_set!" unless log_prefix.nil?
  322. file_set.parent.total_file_size_add_file_set! file_set
  323. end
  324. Rails.logger.info "end IngestHelper.update_total_file_size"
  325. rescue Exception => e # rubocop:disable Lint/RescueException
  326. Rails.logger.error "IngestHelper.update_total_file_size(#{file_set}) #{e.class}: #{e.message} at #{e.backtrace[0]}"
  327. end
  328. 1 def self.virus_scan( file_set )
  329. LoggingHelper.bold_debug "IngestHelper.virus_scan #{file_set}"
  330. file_set.virus_scan
  331. rescue Exception => e # rubocop:disable Lint/RescueException
  332. Rails.logger.error "IngestHelper.virus_scan(#{file_set}) #{e.class}: #{e.message} at #{e.backtrace[0]}"
  333. end
  334. end
  335. end

app/helpers/deepblue/jira_helper.rb

22.77% lines covered

101 relevant lines. 23 lines covered and 78 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 require 'jira-ruby'
  4. 1 module JiraHelper
  5. 1 extend ActionView::Helpers::TranslationHelper
  6. 1 FIELD_NAME_CONTACT_INFO = "customfield_11315".freeze
  7. 1 FIELD_NAME_CREATOR = "customfield_11304".freeze
  8. 1 FIELD_NAME_DEPOSIT_ID = "customfield_11303".freeze
  9. 1 FIELD_NAME_DEPOSIT_URL = "customfield_11305".freeze
  10. 1 FIELD_NAME_DESCRIPTION = "description".freeze
  11. 1 FIELD_NAME_DISCIPLINE = "customfield_11309".freeze
  12. 1 FIELD_NAME_STATUS = "customfield_12000".freeze
  13. 1 FIELD_NAME_SUMMARY = "summary".freeze
  14. FIELD_VALUES_DISCIPLINE_MAP = {
  15. 1 "Arts" =>
  16. [{
  17. # "self" => "https://tools.lib.umich.edu/jira/rest/api/2/customFieldOption/11303",
  18. "value" => "Arts",
  19. "id" => "11303"
  20. }],
  21. "Business" =>
  22. [{
  23. # "self" => "https://tools.lib.umich.edu/jira/rest/api/2/customFieldOption/10820",
  24. "value" => "Business",
  25. "id" => "10820"
  26. }],
  27. "Engineering" =>
  28. [{
  29. # "self" => "https://tools.lib.umich.edu/jira/rest/api/2/customFieldOption/10821",
  30. "value" => "Engineering",
  31. "id" => "10821"
  32. }],
  33. "General Information Sources" =>
  34. [{
  35. # "self" => "https://tools.lib.umich.edu/jira/rest/api/2/customFieldOption/11304",
  36. "value" => "General Information Sources",
  37. "id" => "11304"
  38. }],
  39. "Government, Politics, and Law" =>
  40. [{
  41. # "self" => "https://tools.lib.umich.edu/jira/rest/api/2/customFieldOption/11305",
  42. "value" => "Government, Politics, and Law",
  43. "id" => "11305"
  44. }],
  45. "Health Sciences" =>
  46. [{
  47. # "self" => "https://tools.lib.umich.edu/jira/rest/api/2/customFieldOption/10822",
  48. "value" => "Health Sciences",
  49. "id" => "10822"
  50. }],
  51. "Humanities" =>
  52. [{
  53. # "self" => "https://tools.lib.umich.edu/jira/rest/api/2/customFieldOption/11306",
  54. "value" => "Humanities",
  55. "id" => "11306"
  56. }],
  57. "International Studies" =>
  58. [{
  59. # "self" => "https://tools.lib.umich.edu/jira/rest/api/2/customFieldOption/11307",
  60. "value" => "International Studies",
  61. "id" => "11307"
  62. }],
  63. "News and Current Events" =>
  64. [{
  65. # "self" => "https://tools.lib.umich.edu/jira/rest/api/2/customFieldOption/11308",
  66. "value" => "News and Current Events",
  67. "id" => "11308"
  68. }],
  69. "Science" =>
  70. [{
  71. # "self" => "https://tools.lib.umich.edu/jira/rest/api/2/customFieldOption/10824",
  72. "value" => "Science",
  73. "id" => "10824"
  74. }],
  75. "Social Sciences" =>
  76. [{
  77. # "self" => "https://tools.lib.umich.edu/jira/rest/api/2/customFieldOption/10825",
  78. "value" => "Social Sciences",
  79. "id" => "10825"
  80. }],
  81. "Other" =>
  82. [{
  83. # "self" => "https://tools.lib.umich.edu/jira/rest/api/2/customFieldOption/10823",
  84. "value" => "Other",
  85. "id" => "10823"
  86. }]
  87. }.freeze
  88. 1 def self.jira_enabled
  89. DeepBlueDocs::Application.config.jira_integration_enabled
  90. end
  91. 1 def self.jira_manager_issue_type
  92. DeepBlueDocs::Application.config.jira_manager_issue_type
  93. end
  94. 1 def self.jira_manager_project_key
  95. DeepBlueDocs::Application.config.jira_manager_project_key
  96. end
  97. 1 def self.jira_test_mode
  98. DeepBlueDocs::Application.config.jira_test_mode
  99. end
  100. 1 def self.summary_last_name( curation_concern: )
  101. name = Array( curation_concern.creator ).first
  102. return "" if name.blank?
  103. match = name.match( /^([^,]+),.*$/ ) # first non-comma substring
  104. return match[1] if match
  105. match = name.match( /^.* ([^ ]+)$/ ) # last non-space substring
  106. return match[1] if match
  107. return name
  108. end
  109. 1 def self.summary_description( curation_concern: )
  110. description = Array( curation_concern.description ).first
  111. return "" if description.blank?
  112. match = description.match( /^([^ ]+) +([^ ]+) [^ ].*$/ ) # three plus words
  113. return "#{match[1]}#{match[2]}" if match
  114. match = description.match( /^([^ ]+) +([^ ]+)$/ ) # two words
  115. return "#{match[1]}#{match[2]}" if match
  116. match = description.match( /^[^ ]+$/ ) # one word
  117. return description if match
  118. return description
  119. end
  120. 1 def self.summary_title( curation_concern: )
  121. title = Array( curation_concern.title ).first
  122. return "" if title.blank?
  123. match = title.match( /^([^ ]+) +([^ ]+) [^ ].*$/ ) # three plus words
  124. return "#{match[1]}#{match[2]}" if match
  125. match = title.match( /^([^ ]+) +([^ ]+)$/ ) # two words
  126. return "#{match[1]}#{match[2]}" if match
  127. match = title.match( /^[^ ]+$/ ) # one word
  128. return title if match
  129. return title
  130. end
  131. 1 def self.jira_ticket_for_create( curation_concern: )
  132. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  133. Deepblue::LoggingHelper.called_from,
  134. "curation_concern.id=#{curation_concern.id}",
  135. "" ]
  136. # Issue type: Data deposit
  137. #
  138. # * issue type field name: "issuetype"
  139. #
  140. # Status: New
  141. #
  142. # * status field name: "customfield_12000"
  143. #
  144. # Summary: [Depositor last name] _ [First two words of deposit] _ [deposit ID] - e.g., Nasser_BootAcceleration_n583xv03w
  145. #
  146. # * summary field name: "summary"
  147. #
  148. # Requester/contact: "Creator", "Contact information" fields in DBD - e.g., Meurer, William wmeurer@med.umich.edu
  149. #
  150. # * creator field name: "customfield_11304"
  151. # * contact information field name: "customfield_11315"
  152. #
  153. # Unique Identifier: Deposit ID (from deposit URL) - e.g., n583xv03w
  154. #
  155. # * unique identifier field name: "customfield_11303"
  156. #
  157. # URL in Deep Blue Data: Deposit URL - e.g., https://deepblue.lib.umich.edu/data/concern/data_sets/4x51hj04n
  158. #
  159. # * deposit url field name: "customfield_11305"
  160. #
  161. # Description: "Title of deposit" - e.g., Effect of financial incentives on head CT use dataset"
  162. #
  163. # * description field name: "description"
  164. #
  165. # Discipline: "Discipline" field in DBD - e.g., Health sciences
  166. #
  167. # * discipline field name: "customfield_11309"
  168. #
  169. summary_title = summary_title( curation_concern: curation_concern )
  170. summary_last_name = summary_last_name( curation_concern: curation_concern )
  171. summary = "#{summary_last_name}_#{summary_title}_#{curation_concern.id}"
  172. contact_info = curation_concern.authoremail
  173. creator = Array( curation_concern.creator ).first
  174. deposit_id = curation_concern.id
  175. deposit_url = ::Deepblue::EmailHelper.data_set_url( data_set: curation_concern )
  176. discipline = Array( curation_concern.subject_discipline ).first
  177. description = Array( curation_concern.title ).join("\n") + "\n\nby #{creator}"
  178. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  179. Deepblue::LoggingHelper.called_from,
  180. Deepblue::LoggingHelper.obj_class( 'class', self ),
  181. "summary=#{summary}",
  182. "description=#{description}",
  183. "" ]
  184. jira_url = JiraHelper.new_ticket( contact_info: contact_info,
  185. deposit_id: deposit_id,
  186. deposit_url: deposit_url,
  187. description: description,
  188. discipline: discipline,
  189. summary: summary )
  190. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  191. Deepblue::LoggingHelper.called_from,
  192. "jira_url=#{jira_url}",
  193. "" ]
  194. return if jira_url.nil?
  195. return unless curation_concern.respond_to? :curation_notes_admin
  196. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  197. Deepblue::LoggingHelper.called_from,
  198. "curation_concern.curation_notes_admin=#{curation_concern.curation_notes_admin}",
  199. "" ]
  200. curation_concern.date_modified = DateTime.now # touch it so it will save updated attributes
  201. notes = curation_concern.curation_notes_admin
  202. notes = [] if notes.nil?
  203. curation_concern.curation_notes_admin = notes << "Jira ticket: #{jira_url}"
  204. curation_concern.save!
  205. end
  206. 1 def self.new_ticket( project_key: jira_manager_project_key,
  207. issue_type: jira_manager_issue_type,
  208. contact_info:,
  209. deposit_id:,
  210. deposit_url:,
  211. description:,
  212. discipline:,
  213. summary: )
  214. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  215. Deepblue::LoggingHelper.called_from,
  216. Deepblue::LoggingHelper.obj_class( 'class', self ),
  217. "summary=#{summary}",
  218. "project_key=#{project_key}",
  219. "issue_type=#{issue_type}",
  220. "description=#{description}",
  221. "jira_enabled=#{jira_enabled}",
  222. "" ]
  223. return nil unless jira_enabled
  224. client_options = {
  225. :username => Settings.jira.username,
  226. :password => Settings.jira.password,
  227. :site => Settings.jira.site_url,
  228. # :site => 'https://tools.lib.umich.edu',
  229. :context_path => '/jira',
  230. :auth_type => :basic
  231. }
  232. save_options = {
  233. "fields" => {
  234. "project" => { "key" => project_key },
  235. "issuetype" => { "name" => issue_type },
  236. FIELD_NAME_CONTACT_INFO => contact_info,
  237. FIELD_NAME_DEPOSIT_ID => deposit_id,
  238. FIELD_NAME_DEPOSIT_URL => deposit_url,
  239. FIELD_NAME_DESCRIPTION => description,
  240. FIELD_NAME_DISCIPLINE => discipline,
  241. FIELD_NAME_SUMMARY => summary }
  242. }
  243. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  244. Deepblue::LoggingHelper.called_from,
  245. "client_options=#{client_options}",
  246. "save_options=#{save_options}",
  247. "" ]
  248. return "https://test.jira.url/#{project_key}" if jira_test_mode
  249. # return nil if jira_test_mode
  250. client = JIRA::Client.new( client_options )
  251. # issue = client.Issue.build
  252. # rv = issue.save( save_options )
  253. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  254. # Deepblue::LoggingHelper.called_from,
  255. # "issue.save rv=#{rv}",
  256. # "" ]
  257. build_options = {
  258. "fields" => {
  259. FIELD_NAME_SUMMARY => summary,
  260. "project" => { "key" => project_key },
  261. "issuetype" => { "name" => issue_type },
  262. FIELD_NAME_DESCRIPTION => description }
  263. }
  264. issue = client.Issue.build
  265. rv = issue.save( build_options )
  266. ::Deepblue::LoggingHelper.bold_debug( [ Deepblue::LoggingHelper.here,
  267. Deepblue::LoggingHelper.called_from,
  268. "issue.save( #{build_options} ) rv=#{rv}",
  269. "" ] ) unless rv
  270. sopts = { "fields" => { FIELD_NAME_CONTACT_INFO => contact_info } }
  271. rv = issue.save( sopts )
  272. ::Deepblue::LoggingHelper.bold_debug( [ Deepblue::LoggingHelper.here,
  273. Deepblue::LoggingHelper.called_from,
  274. "issue.save( #{sopts} ) rv=#{rv}",
  275. "" ] ) unless rv
  276. sopts = { "fields" => { FIELD_NAME_DEPOSIT_ID => deposit_id } }
  277. rv = issue.save( sopts )
  278. ::Deepblue::LoggingHelper.bold_debug( [ Deepblue::LoggingHelper.here,
  279. Deepblue::LoggingHelper.called_from,
  280. "issue.save( #{sopts} ) rv=#{rv}",
  281. "" ] ) unless rv
  282. sopts = { "fields" => { FIELD_NAME_DEPOSIT_URL => deposit_url } }
  283. rv = issue.save( sopts )
  284. ::Deepblue::LoggingHelper.bold_debug( [ Deepblue::LoggingHelper.here,
  285. Deepblue::LoggingHelper.called_from,
  286. "issue.save( #{sopts} ) rv=#{rv}",
  287. "" ] ) unless rv
  288. sopts = { "fields" => { FIELD_NAME_DISCIPLINE => FIELD_VALUES_DISCIPLINE_MAP[discipline] } }
  289. rv = issue.save( sopts )
  290. ::Deepblue::LoggingHelper.bold_debug( [ Deepblue::LoggingHelper.here,
  291. Deepblue::LoggingHelper.called_from,
  292. "issue.save( #{sopts} ) rv=#{rv}",
  293. "" ] ) unless rv
  294. # if rv is false, the save failed.
  295. url = ticket_url( client: client, issue: issue )
  296. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  297. Deepblue::LoggingHelper.called_from,
  298. "url=#{url}",
  299. "" ]
  300. return url
  301. end
  302. 1 def self.ticket_url( client:, issue: )
  303. issue_key = issue.key if issue.respond_to? :key
  304. "#{client.options[:site]}#{client.options[:context_path]}/browse/#{issue.key}"
  305. end
  306. end
  307. end

app/helpers/deepblue/json_logger_helper.rb

79.26% lines covered

135 relevant lines. 107 lines covered and 28 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 class LogParseError < RuntimeError
  4. end
  5. 1 module JsonLoggerHelper
  6. 1 TIMESTAMP_FORMAT = '\d\d\d\d\-\d\d\-\d\d \d\d:\d\d:\d\d'.freeze
  7. 1 RE_TIMESTAMP_FORMAT = Regexp.compile "^#{TIMESTAMP_FORMAT}$".freeze
  8. # Format: Date Timestamp Event/Event_detail_possibly_empty/ClassName/ID_possibly_empty Rest_in_form_of_JSON_hash
  9. 1 RE_LOG_LINE = Regexp.compile "^(#{TIMESTAMP_FORMAT}) ([^/]+)/([^/]*)/([^/]+)/([^/ ]*) (.*)$".freeze
  10. 1 PREFIX_UPDATE_ATTRIBUTE = 'UpdateAttribute_'.freeze
  11. 1 module ClassMethods
  12. 1 def extract_embargo_form_values( curation_concern:, update_key_prefix:, form_params: )
  13. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  14. ::Deepblue::LoggingHelper.called_from,
  15. ::Deepblue::LoggingHelper.obj_class( "curation_concern", curation_concern ),
  16. "curation_concern.id=#{curation_concern.id}",
  17. "update_key_prefix=#{update_key_prefix}",
  18. "form_params=#{form_params}",
  19. "" ]
  20. embargo_values = {}
  21. key = "embargo_release_date"
  22. new_value = form_params[key]
  23. old_value = curation_concern.embargo_release_date if curation_concern.respond_to? :embargo_release_date
  24. update_key = "#{update_key_prefix}#{key}".to_sym
  25. embargo_values[update_key] = form_update_attribute( key: :embargo_release_date,
  26. old_value: old_value,
  27. new_value: new_value )
  28. key = "visibility_during_embargo"
  29. new_value = form_params[key]
  30. old_value = curation_concern.visibility_during_embargo if curation_concern.respond_to? :visibility_during_embargo
  31. update_key = "#{update_key_prefix}#{key}".to_sym
  32. embargo_values[update_key] = form_update_attribute( key: :visibility_during_embargo,
  33. old_value: old_value,
  34. new_value: new_value )
  35. key = "visibility_after_embargo"
  36. new_value = form_params[key]
  37. old_value = curation_concern.visibility_after_embargo if curation_concern.respond_to? :visibility_after_embargo
  38. update_key = "#{update_key_prefix}#{key}".to_sym
  39. embargo_values[update_key] = form_update_attribute( key: :visibility_after_embargo,
  40. old_value: old_value,
  41. new_value: new_value )
  42. embargo_values
  43. end
  44. 1 def form_update_attribute( key:, old_value:, new_value: )
  45. 4 old_value = ActiveSupport::JSON.encode old_value
  46. 4 old_value = ActiveSupport::JSON.decode old_value
  47. 4 attr = { attribute: key, old_value: old_value, new_value: new_value }
  48. 4 attr
  49. end
  50. 1 def form_params_to_update_attribute_key_values( curation_concern:,
  51. form_params:,
  52. update_key_prefix: PREFIX_UPDATE_ATTRIBUTE,
  53. delta_only: true )
  54. 4 attr_key_values = {}
  55. 4 return attr_key_values if form_params.nil?
  56. 4 embargo_values = nil
  57. 4 form_params.each_pair do |key, value|
  58. 102 update_key = "#{update_key_prefix}#{key}".to_sym
  59. 102 key = key.to_sym
  60. 102 has_old_value = case key
  61. when :visibility
  62. 4 old_value = curation_concern.visibility
  63. embargo_values = extract_embargo_form_values( curation_concern: curation_concern,
  64. update_key_prefix: update_key_prefix,
  65. 4 form_params: form_params ) if value == "embargo"
  66. 4 true
  67. else
  68. 98 if curation_concern.has_attribute? key
  69. 58 old_value = curation_concern[key]
  70. 58 true
  71. else
  72. 40 false
  73. end
  74. end
  75. 102 next unless has_old_value
  76. 62 if value.is_a? Array
  77. 30 if value.blank?
  78. value = nil
  79. 30 elsif [''] == value
  80. 14 value = nil
  81. 16 elsif 1 < value.size
  82. 16 value.pop if '' == value.last
  83. end
  84. end
  85. # old_value = curation_concern[key]
  86. 62 new_value = nil
  87. 62 if delta_only
  88. 62 unless old_value.blank? && value.blank?
  89. # old_value = ActiveSupport::JSON.encode old_value
  90. # old_value = ActiveSupport::JSON.decode old_value
  91. # attr_key_values[update_key] = { key: key, old_value: old_value, new_value: value } unless old_value == value
  92. 32 new_value = value unless old_value == value
  93. end
  94. else
  95. # old_value = ActiveSupport::JSON.encode old_value
  96. # old_value = ActiveSupport::JSON.decode old_value
  97. # attr_key_values[update_key] = { key: key, old_value: old_value, new_value: value }
  98. new_value = value
  99. end
  100. 62 next if new_value.nil?
  101. 4 attr_key_values[update_key] = form_update_attribute( key: key, old_value: old_value, new_value: value )
  102. end
  103. 4 attr_key_values[:embargo] = embargo_values if embargo_values.present?
  104. 4 attr_key_values
  105. end
  106. 1 def logger_initialize_key_values( user_email:, event_note:, **added_key_values )
  107. 9 key_values = { user_email: user_email }
  108. 9 key_values.merge!( event_note: event_note ) if event_note.present?
  109. 9 key_values.merge!( added_key_values ) if added_key_values.present?
  110. 9 key_values
  111. end
  112. 1 def logger_json_encode( value:, json_encode: true )
  113. 9 return value unless json_encode
  114. begin
  115. 9 return ActiveSupport::JSON.encode value
  116. rescue Exception => e # rubocop:disable Lint/RescueException
  117. Rails.logger.error "#{e.class}: #{e.message} at #{e.backtrace[0]}"
  118. return value.to_s unless value.respond_to? :each_pair
  119. new_value = {}
  120. value.each_pair do |key, val|
  121. new_value[key] = logger_json_encode( value: val )
  122. end
  123. return ActiveSupport::JSON.encode new_value
  124. end
  125. end
  126. 1 def msg_to_log( class_name:,
  127. event:,
  128. event_note:,
  129. id:,
  130. timestamp:,
  131. time_zone:,
  132. json_encode: true,
  133. **log_key_values )
  134. 9 if event_note.blank?
  135. 4 key_values = { event: event, timestamp: timestamp, time_zone: time_zone, class_name: class_name, id: id }
  136. 4 event += '/'
  137. else
  138. 5 key_values = { event: event,
  139. event_note: event_note,
  140. timestamp: timestamp,
  141. time_zone: time_zone,
  142. class_name: class_name,
  143. id: id }
  144. 5 event = "#{event}/#{event_note}"
  145. end
  146. 9 key_values.merge! log_key_values
  147. 9 key_values = logger_json_encode(value: key_values, json_encode: json_encode )
  148. 9 "#{timestamp} #{event}/#{class_name}/#{id} #{key_values}"
  149. end
  150. 1 def parse_log_line( line, line_number: nil, raw_key_values: false )
  151. # line is of the form: "timestamp event/event_note/class_name/id key_values"
  152. 10 match = RE_LOG_LINE.match line
  153. 10 unless match
  154. 3 msg = "parse of log line failed: '#{line}'" if line_number.blank?
  155. 3 msg = "parse of log line failed at line #{line_number}: '#{line}'" if line_number.present?
  156. 3 raise LogParseError, msg
  157. end
  158. 7 timestamp = match[1]
  159. 7 event = match[2]
  160. 7 event_note = match[3]
  161. 7 class_name = match[4]
  162. 7 id = match[5]
  163. 7 key_values = match[6]
  164. 7 key_values = parse_log_line_key_values key_values unless raw_key_values
  165. 7 return timestamp, event, event_note, class_name, id, key_values
  166. end
  167. 1 def parse_log_line_key_values( key_values )
  168. 7 ActiveSupport::JSON.decode key_values
  169. end
  170. 1 def system_as_current_user
  171. 1 "Deepblue"
  172. end
  173. 1 def timestamp_now
  174. 4 Time.now.to_formatted_s(:db )
  175. end
  176. 1 def timestamp_zone
  177. 2 DeepBlueDocs::Application.config.timezone_zone
  178. end
  179. 1 def to_log_format_timestamp( timestamp )
  180. 21 is_a_string = timestamp.is_a?( String )
  181. 21 return timestamp if is_a_string && RE_TIMESTAMP_FORMAT =~ timestamp
  182. 20 timestamp = Time.parse( timestamp ) if is_a_string
  183. 20 timestamp = timestamp.to_formatted_s( :db ) if timestamp.is_a? Time
  184. 20 timestamp.to_s
  185. end
  186. 1 def update_attribute_key_values( curation_concern:,
  187. update_key_prefix: PREFIX_UPDATE_ATTRIBUTE,
  188. **update_attr_key_values )
  189. 2 return nil if update_attr_key_values.blank?
  190. 2 new_update_attr_key_values = {}
  191. 2 key_values = update_attr_key_values
  192. 2 key_values = key_values[:update_attr_key_values] if key_values.key?( :update_attr_key_values )
  193. # puts ActiveSupport::JSON.encode key_values
  194. 2 key_values.each_pair do |key, value|
  195. # puts "#{key}:-#{value}"
  196. 2 next unless key.to_s.start_with? update_key_prefix
  197. 2 attribute = value[:attribute]
  198. 2 old_value = value[:old_value]
  199. 2 new_value = curation_concern_attribute( curation_concern: curation_concern, attribute: attribute )
  200. # puts "#{attribute}, #{old_value}, #{new_value}"
  201. new_update_attr_key_values[key] = { attribute: attribute,
  202. old_value: old_value,
  203. 2 new_value: new_value } unless old_value == new_value
  204. end
  205. 2 return new_update_attr_key_values
  206. end
  207. 1 def curation_concern_attribute( curation_concern:, attribute: )
  208. 2 case attribute
  209. when :visibility
  210. curation_concern.visibility
  211. else
  212. 2 curation_concern[attribute]
  213. end
  214. end
  215. end
  216. 1 extend ClassMethods
  217. 1 def self.included( base )
  218. 2 base.extend( ClassMethods )
  219. end
  220. end
  221. end

app/helpers/deepblue/logging_helper.rb

72.22% lines covered

72 relevant lines. 52 lines covered and 20 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 module LoggingHelper
  4. 1 def self.bold_debug( msg = nil, label: nil, key_value_lines: true, lines: 1, &block )
  5. 22 lines = 1 unless lines.positive?
  6. 45 lines.times { Rails.logger.debug ">>>>>>>>>>" }
  7. 22 Rails.logger.debug label if label.present?
  8. 22 if msg.respond_to?( :each )
  9. 20 msg.each do |m|
  10. 151 if key_value_lines && m.respond_to?( :each_pair )
  11. 3 m.each_pair { |k, v| Rails.logger.debug "#{k}: #{v}" }
  12. else
  13. 150 Rails.logger.debug m
  14. end
  15. end
  16. 20 Rails.logger.debug nil, &block if block_given?
  17. else
  18. 2 Rails.logger.debug msg, &block
  19. end
  20. 45 lines.times { Rails.logger.debug ">>>>>>>>>>" }
  21. end
  22. 1 def self.called_from
  23. 15 "called from: #{caller_locations(1, 2)[1]}"
  24. end
  25. 1 def self.caller
  26. "#{caller_locations(1, 2)[1]}"
  27. end
  28. 1 def self.debug( msg = nil, label: nil, key_value_lines: true, lines: 0, &block )
  29. 15 lines = 0 if lines.negative?
  30. 15 lines.times { Rails.logger.debug ">>>>>>>>>>" }
  31. 15 Rails.logger.debug label if label.present?
  32. 15 if msg.respond_to?( :each )
  33. msg.each do |m|
  34. if key_value_lines && m.respond_to?( :each_pair )
  35. m.each_pair { |k, v| Rails.logger.debug "#{k}: #{v}" }
  36. else
  37. Rails.logger.debug m
  38. end
  39. end
  40. Rails.logger.debug nil, &block if block_given?
  41. else
  42. 15 Rails.logger.debug msg, &block
  43. end
  44. 15 lines.times { Rails.logger.debug ">>>>>>>>>>" }
  45. end
  46. 1 def self.here
  47. 15 "#{caller_locations(1, 1)[0]}"
  48. end
  49. 1 def self.initialize_key_values( user_email:, event_note:, **added_key_values )
  50. 5 key_values = { user_email: user_email }
  51. 5 key_values.merge!( event_note: event_note ) if event_note.present?
  52. 5 key_values.merge!( added_key_values ) if added_key_values.present?
  53. 5 key_values
  54. end
  55. 1 def self.log( class_name: 'UnknownClass',
  56. event: 'unknown',
  57. event_note: '',
  58. id: 'unknown_id',
  59. timestamp: LoggingHelper.timestamp_now,
  60. time_zone: LoggingHelper.timestamp_zone,
  61. echo_to_rails_logger: true,
  62. logger: Rails.logger,
  63. **key_values )
  64. msg = msg_to_log( class_name: class_name,
  65. event: event,
  66. event_note: event_note,
  67. id: id,
  68. timestamp: timestamp,
  69. time_zone: time_zone,
  70. **key_values )
  71. logger.info msg
  72. Rails.logger.info msg if echo_to_rails_logger
  73. end
  74. 1 def self.msg_to_log( class_name:,
  75. event:,
  76. event_note:,
  77. id:, timestamp:,
  78. time_zone:,
  79. json_encode: true,
  80. **added_key_values )
  81. 2 if event_note.blank?
  82. 1 key_values = { event: event, timestamp: timestamp, time_zone: time_zone, class_name: class_name, id: id }
  83. 1 event += '/'
  84. else
  85. 1 key_values = { event: event,
  86. event_note: event_note,
  87. timestamp: timestamp,
  88. time_zone: time_zone,
  89. class_name: class_name,
  90. id: id }
  91. 1 event = "#{event}/#{event_note}"
  92. end
  93. 2 key_values.merge! added_key_values
  94. 2 key_values = ActiveSupport::JSON.encode key_values if json_encode
  95. 2 "#{timestamp} #{event}/#{class_name}/#{id} #{key_values}"
  96. end
  97. 1 def self.obj_attribute_names( label, obj )
  98. return "#{label}.attribute_names=N/A" unless obj.respond_to? :attribute_names
  99. "#{label}.attribute_names=#{obj.attribute_names}"
  100. end
  101. 1 def self.obj_class( label, obj )
  102. 9 "#{label}.class=#{obj.class.name}"
  103. end
  104. 1 def self.obj_instance_variables( label, obj )
  105. "#{label}.instance_variables=#{obj.instance_variables}"
  106. end
  107. 1 def self.obj_methods( label, obj )
  108. "#{label}.methods=#{obj.methods.sort}"
  109. end
  110. 1 def self.obj_to_json( label, obj )
  111. return "#{label}.to_json=N/A" unless obj.respond_to? :to_json
  112. "#{label}.to_json=#{obj.to_json}"
  113. end
  114. 1 def self.system_as_current_user
  115. 1 "Deepblue"
  116. end
  117. 1 def self.timestamp_now
  118. Time.now.to_formatted_s(:db )
  119. end
  120. 1 def self.timestamp_zone
  121. DeepBlueDocs::Application.config.timezone_zone
  122. end
  123. 1 def self.to_log_format_timestamp( timestamp )
  124. timestamp = Time.parse( timestamp ) if timestamp.is_a? String
  125. timestamp = timestamp.to_formatted_s( :db ) if timestamp.is_a? Time
  126. timestamp.to_s
  127. end
  128. end
  129. end

app/helpers/deepblue/metadata_helper.rb

19.25% lines covered

504 relevant lines. 97 lines covered and 407 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 module MetadataHelper
  4. 1 SOURCE_DBDv1 = 'DBDv1' # rubocop:disable Style/ConstantName
  5. 1 SOURCE_DBDv2 = 'DBDv2' # rubocop:disable Style/ConstantName
  6. 1 DEFAULT_BASE_DIR = "/deepbluedata-prep/"
  7. 1 DEFAULT_SOURCE = SOURCE_DBDv2
  8. 1 DEFAULT_TASK = 'populate'
  9. 1 FIELD_SEP = '; '
  10. 1 HEADER_TYPE_COLLECTIONS = ':collections:'
  11. 1 HEADER_TYPE_USERS = ':users:'
  12. 1 HEADER_TYPE_WORKS = ':works:'
  13. 1 MODE_APPEND = 'append'
  14. 1 MODE_BUILD = 'build'
  15. 1 MODE_MIGRATE = 'migrate'
  16. 1 PREFIX_COLLECTION = 'c_'
  17. 1 PREFIX_USERS = 'users'
  18. 1 PREFIX_WORK = 'w_'
  19. 1 ATTRIBUTE_NAMES_ALWAYS_INCLUDE_CC = %w[ admin_set_id
  20. authoremail
  21. creator
  22. creator_ordered
  23. curation_notes_admin
  24. curation_notes_admin_ordered
  25. curation_notes_user
  26. curation_notes_user_ordered
  27. date_coverage
  28. date_created
  29. date_modified
  30. date_published
  31. date_uploaded
  32. depositor
  33. description
  34. description_ordered
  35. doi
  36. fundedby
  37. fundedby_other
  38. grantnumber
  39. isReferencedBy
  40. isReferencedBy_ordered
  41. keyword
  42. keyword_ordered
  43. language
  44. language_ordered
  45. methodology
  46. owner
  47. prior_identifier
  48. referenced_by
  49. referenced_by_ordered
  50. rights_license_other
  51. source
  52. subject_discipline
  53. title
  54. title_ordered
  55. tombstone
  56. access_deepblue
  57. access_deepblue_ordered
  58. total_file_size ].freeze
  59. 1 ATTRIBUTE_NAMES_ALWAYS_INCLUDE_FILE_SET = %w[ creator
  60. curation_notes_admin
  61. curation_notes_admin_ordered
  62. curation_notes_user
  63. curation_notes_user_ordered
  64. date_created
  65. date_modified
  66. date_uploaded
  67. depositor
  68. label
  69. owner
  70. prior_identifier
  71. title
  72. virus_scan_service
  73. virus_scan_status
  74. virus_scan_status_date ].freeze
  75. 1 ATTRIBUTE_NAMES_ALWAYS_INCLUDE_USER = %w[ id email ].freeze
  76. 1 ATTRIBUTE_NAMES_IGNORE = %w[ access_control_id
  77. collection_type_gid
  78. file_size
  79. head
  80. part_of tail
  81. thumbnail_id ].freeze
  82. 1 ATTRIBUTE_NAMES_IGNORE_IMPORT = %w[ creator_ordered
  83. curation_notes_admin_ordered
  84. curation_notes_user_ordered
  85. description_ordered
  86. isReferencedBy_ordered
  87. language_ordered
  88. referenced_by_ordered
  89. representative_id
  90. resource_type
  91. title_ordered
  92. total_file_size ].freeze
  93. 1 ATTRIBUTE_NAMES_IGNORE_IMPORT_FILE_SET = %w[ description
  94. file_size
  95. file_size_human_readable
  96. keyword
  97. language
  98. representative_id
  99. resource_type
  100. title ].freeze
  101. 1 ATTRIBUTE_NAMES_MAP_V1_V2 = { 'isReferencedBy': 'referenced_by',
  102. 'rights': 'rights_license',
  103. 'subject': 'subject_discipline' }.freeze
  104. 1 ATTRIBUTE_NAMES_MAP_V2_V1 = {}.freeze
  105. 1 ATTRIBUTE_NAMES_USER_IGNORE = %w[ current_sign_in_at
  106. current_sign_in_ip
  107. reset_password_token
  108. reset_password_sent_at ].freeze
  109. # encrypted_password
  110. 1 def self.attribute_names_always_include_cc
  111. @@attribute_names_always_include ||= init_attribute_names_always_include_cc
  112. end
  113. 1 def self.attribute_names_collection
  114. @@attribute_names_collection ||= Collection.attribute_names.sort
  115. end
  116. 1 def self.attribute_names_file_set
  117. @@attribute_names_file_set ||= FileSet.attribute_names.sort
  118. end
  119. 1 def self.attribute_names_user
  120. @@attribute_names_user ||= User.attribute_names.sort
  121. end
  122. 1 def self.attribute_names_work( source: )
  123. if source == SOURCE_DBDv2
  124. DataSet.attribute_names.sort
  125. else
  126. GenericWork.attribute_names.sort
  127. end
  128. end
  129. 1 def self.init_attribute_names_always_include_cc
  130. rv = {}
  131. ATTRIBUTE_NAMES_ALWAYS_INCLUDE_CC.each { |name| rv[name] = true }
  132. return rv
  133. end
  134. 1 def self.file_from_file_set( file_set )
  135. file = nil
  136. files = file_set.files
  137. unless files.nil? || files.size.zero?
  138. file = files[0]
  139. files.each do |f|
  140. file = f unless f.original_name.empty?
  141. end
  142. end
  143. return file
  144. end
  145. 1 def self.human_readable_size( value )
  146. value = value.to_i
  147. return ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert( value, precision: 3 )
  148. end
  149. 1 def self.log_lines( filename, *lines )
  150. File.open( filename, "a" ) do |f|
  151. lines.each { |line| f.puts line }
  152. end
  153. end
  154. 1 def self.log_provenance_migrate( curation_concern:, parent: nil, migrate_direction: 'export', source: )
  155. if source == SOURCE_DBDv1
  156. msg = "Migrate #{migrate_direction} #{curation_concern.class.name} #{curation_concern.id}"
  157. msg += " parent_id: #{parent.id}" if parent.present?
  158. PROV_LOGGER.info( msg )
  159. else
  160. return unless curation_concern.respond_to? :provenance_migrate
  161. parent_id = nil
  162. parent_id = parent.id if parent.present?
  163. curation_concern.provenance_migrate( current_user: nil,
  164. parent_id: parent_id,
  165. migrate_direction: migrate_direction )
  166. end
  167. end
  168. 1 def self.metadata_filename_collection( pathname_dir, collection )
  169. pathname_dir.join "w_#{collection.id}_metadata_report.txt"
  170. end
  171. 1 def self.metadata_filename_collection_work( pathname_dir, collection, work )
  172. pathname_dir.join "c_#{collection.id}_w_#{work.id}_metadata_report.txt"
  173. end
  174. 1 def self.metadata_filename_work( pathname_dir, work )
  175. pathname_dir.join "w_#{work.id}_metadata_report.txt"
  176. end
  177. 1 def self.metadata_multi_valued?( attribute_value )
  178. return false if attribute_value.blank?
  179. return true if attribute_value.respond_to?( :each ) && 1 < attribute_value.size
  180. false
  181. end
  182. 1 def self.ordered( ordered_values: nil, values: nil )
  183. 3137 return nil if values.nil?
  184. 3137 if DeepBlueDocs::Application.config.do_ordered_list_hack
  185. 3137 unless ordered_values.nil?
  186. begin
  187. 467 values = OrderedStringHelper.deserialize( ordered_values )
  188. rescue OrderedStringHelper::DeserializeError
  189. # fallback to original values, which are stored in an unspecified order
  190. return values
  191. end
  192. end
  193. end
  194. 3137 return values
  195. end
  196. 1 def self.ordered_values( ordered_values: nil, values: nil )
  197. 88 return nil if values.nil?
  198. 88 rv = nil
  199. 88 if DeepBlueDocs::Application.config.do_ordered_list_hack
  200. 88 if DeepBlueDocs::Application.config.do_ordered_list_hack_save
  201. 88 rv = OrderedStringHelper.serialize( values )
  202. elsif !ordered_values.nil?
  203. rv = OrderedStringHelper.serialize( values )
  204. end
  205. end
  206. 88 return rv
  207. end
  208. 1 def self.report_collection( collection, dir: nil, out: nil, depth: '==' )
  209. target_file = nil
  210. if out.nil?
  211. target_file = metadata_filename_collection( dir, collection )
  212. open( target_file, 'w' ) do |out2|
  213. report_collection( collection, out: out2, depth: depth )
  214. end
  215. else
  216. title = report_title( collection, field_sep: '' )
  217. out.puts "#{depth} Collection: #{title} #{depth}"
  218. report_item( out, "ID: ", collection.id )
  219. report_item( out, "Title: ", collection.title, one_line: true )
  220. report_item( out, "Total items: ", collection.member_objects.count )
  221. report_item( out, "Total size: ", human_readable_size( collection.bytes ) )
  222. report_item( out, "Creator: ", collection.creator, one_line: false, item_prefix: "\t" )
  223. report_item( out, "Keyword: ", collection.keyword, one_line: false, item_prefix: "\t" )
  224. report_item( out, "Discipline: ", collection.subject_discipline, one_line: false, item_prefix: "\t" )
  225. report_item( out, "Language: ", collection.language )
  226. report_item( out, "Citation to related material: ", collection.referenced_by )
  227. report_item( out, "Visibility: ", collection.visibility )
  228. if collection.member_objects.count.positive?
  229. collection.member_objects.each do |work|
  230. out.puts
  231. report_work(work, out: out, depth: "=#{depth}" )
  232. end
  233. end
  234. end
  235. return target_file
  236. end
  237. 1 def self.report_collection_work( collection, work, dir: nil, out: nil, depth: '==' )
  238. target_file = nil
  239. if out.nil?
  240. target_file = metadata_filename_collection_work( dir, collection, work )
  241. open( target_file, 'w' ) do |out2|
  242. report_collection_work( collection, work, out: out2, depth: depth )
  243. end
  244. else
  245. report_work( work, out: out, depth: depth )
  246. end
  247. return target_file
  248. end
  249. 1 def self.report_file_set( file_set, out: nil, depth: '==' )
  250. out.puts "#{depth} File Set: #{file_set.label} #{depth}"
  251. report_item( out, "ID: ", file_set.id )
  252. report_item( out, "File name: ", file_set.label )
  253. report_item( out, "Date uploaded: ", file_set.date_uploaded )
  254. report_item( out, "Date modified: ", file_set.date_modified )
  255. report_item( out, "Total file size: ", human_readable_size( file_set.file_size[0] ) )
  256. report_item( out, "Checksum: ", file_set.original_checksum )
  257. report_item( out, "Mimetype: ", file_set.mime_type )
  258. end
  259. 1 def self.report_work( work, dir: nil, out: nil, depth: '==' )
  260. target_file = nil
  261. if out.nil?
  262. target_file = metadata_filename_work( dir, work )
  263. open( target_file, 'w' ) do |out2|
  264. report_work(work, out: out2, depth: depth )
  265. end
  266. else
  267. title = report_title( work, field_sep: '' )
  268. out.puts "#{depth} Generic Work: #{title} #{depth}"
  269. report_item( out, "ID: ", work.id )
  270. report_item( out, "Title: ", work.title, one_line: true )
  271. report_item( out, "Prior Identifier: ", work.prior_identifier, one_line: true )
  272. report_item( out, "Methodology: ", work.methodology )
  273. report_item( out, "Description: ", work.description, one_line: false, item_prefix: "\t" )
  274. report_item( out, "Creator: ", work.creator, one_line: false, item_prefix: "\t" )
  275. report_item( out, "Depositor: ", work.depositor )
  276. report_item( out, "Contact: ", work.authoremail )
  277. report_item( out, "Discipline: ", work.subject_discipline, one_line: false, item_prefix: "\t" )
  278. report_item( out, "Funded by: ", work.fundedby )
  279. report_item( out, "Funded by Other: ", work.fundedby_other ) if report_source == SOURCE_DBDv2
  280. report_item( out, "ORSP Grant Number: ", work.grantnumber )
  281. report_item( out, "Keyword: ", work.keyword, one_line: false, item_prefix: "\t" )
  282. report_item( out, "Date coverage: ", work.date_coverage )
  283. report_item( out, "Citation to related material: ", work.referenced_by )
  284. report_item( out, "Language: ", work.language )
  285. report_item( out, "Total file count: ", work.file_set_ids.count )
  286. report_item( out, "Total file size: ", human_readable_size( work.total_file_size ) )
  287. report_item( out, "DOI: ", work.doi, optional: true )
  288. report_item( out, "Visibility: ", work.visibility )
  289. report_item( out, "Rights: ", work.rights_license )
  290. report_item( out, "Rights (other): ", work.rights_license_other ) if report_source == SOURCE_DBDv2
  291. report_item( out, "Admin set id: ", work.admin_set_id )
  292. report_item( out, "Tombstone: ", work.tombstone, optional: true )
  293. if work.file_sets.count.positive?
  294. work.file_sets.each do |file_set|
  295. out.puts
  296. report_file_set( file_set, out: out, depth: "=#{depth}" )
  297. end
  298. end
  299. end
  300. return target_file
  301. end
  302. 1 def self.report_item( out,
  303. label,
  304. value,
  305. item_prefix: '',
  306. item_postfix: '',
  307. item_seperator: FIELD_SEP,
  308. one_line: nil,
  309. optional: false )
  310. multi_item = value.respond_to?( :count ) && value.respond_to?( :each )
  311. if optional
  312. return if value.nil?
  313. return if value.to_s.empty?
  314. return if multi_item && value.count.zero?
  315. end
  316. if one_line.nil?
  317. one_line = true
  318. if multi_item
  319. one_line = false if 1 < value.count
  320. end
  321. end
  322. if one_line
  323. if value.respond_to?( :join )
  324. out.puts( "#{label}#{item_prefix}#{value.join( "#{item_prefix}#{item_seperator}#{item_postfix}" )}#{item_postfix}" )
  325. elsif multi_item
  326. out.print( label.to_s )
  327. count = 0
  328. value.each do |item|
  329. count += 1
  330. out.print( "#{item_prefix}#{item}#{item_postfix}" )
  331. out.print( item_seperator.to_s ) unless value.count == count
  332. end
  333. out.puts
  334. else
  335. out.puts( "#{label}#{item_prefix}#{value}#{item_postfix}" )
  336. end
  337. else
  338. out.puts( label.to_s )
  339. if multi_item
  340. value.each { |item| out.puts( "#{item_prefix}#{item}#{item_postfix}" ) }
  341. else
  342. out.puts( "#{item_prefix}#{value}#{item_postfix}" )
  343. end
  344. end
  345. end
  346. 1 def self.report_source
  347. SOURCE_DBDv2
  348. end
  349. 1 def self.report_title( curation_concern, field_sep: FIELD_SEP )
  350. curation_concern.title.join( field_sep )
  351. end
  352. 1 def self.yaml_body_collections( out, indent:, curation_concern:, source: )
  353. yaml_item( out, indent, ":id:", curation_concern.id )
  354. if source == SOURCE_DBDv2
  355. yaml_item( out, indent, ":collection_type:", curation_concern.collection_type.machine_id, escape: true )
  356. # yaml_item( out, indent, ":collection_type_gid:", curation_concern.collection_type_gid, escape: true )
  357. end
  358. # yaml_item( out, indent, ":creator:", curation_concern.creator, escape: true )
  359. # yaml_item( out, indent, ":date_created:", curation_concern.date_created )
  360. # yaml_item( out, indent, ":date_modified:", curation_concern.date_modified )
  361. # yaml_item( out, indent, ":description:", curation_concern.description, escape: true )
  362. # yaml_item( out, indent, ":depositor:", curation_concern.depositor )
  363. # yaml_item( out, indent, ":doi:", curation_concern.doi, escape: true )
  364. yaml_item( out, indent, ":edit_users:", curation_concern.edit_users, escape: true )
  365. # yaml_item( out, indent, ':keyword:', curation_concern.keyword, escape: true )
  366. # yaml_item( out, indent, ":language:", curation_concern.language, escape: true )
  367. yaml_item_prior_identifier( out, indent, curation_concern: curation_concern, source: source )
  368. # yaml_item_referenced_by( out, indent, curation_concern: curation_concern, source: source )
  369. yaml_item_subject( out, indent, curation_concern: curation_concern, source: source )
  370. # yaml_item( out, indent, ':title:', curation_concern.title, escape: true )
  371. # yaml_item( out, indent, ":tombstone:", curation_concern.tombstone, single_value: true )
  372. yaml_item( out, indent, ":total_work_count:", curation_concern.work_ids.count )
  373. yaml_item( out, indent, ":total_file_size:", curation_concern.total_file_size )
  374. yaml_item( out,
  375. indent,
  376. ":total_file_size_human_readable:",
  377. human_readable_size( curation_concern.total_file_size ),
  378. escape: true )
  379. yaml_item( out, indent, ":visibility:", curation_concern.visibility )
  380. skip = %w[ prior_identifier rights rights_license subject subject_discipline total_file_size ]
  381. attribute_names_collection.each do |name|
  382. next if skip.include? name
  383. yaml_item_collection( out, indent, curation_concern, name: name )
  384. end
  385. end
  386. # def self.yaml_body_collections2( out, indent:, curation_concern:, source: )
  387. # yaml_item( out, indent, ":id:", curation_concern.id )
  388. # if source == SOURCE_DBDv2
  389. # yaml_item( out, indent, ":collection_type:", curation_concern.collection_type.machine_id, escape: true )
  390. # yaml_item( out, indent, ":collection_type_gid:", curation_concern.collection_type_gid, escape: true )
  391. # end
  392. # yaml_item( out, indent, ":creator:", curation_concern.creator, escape: true )
  393. # yaml_item( out, indent, ":date_created:", curation_concern.date_created )
  394. # yaml_item( out, indent, ":date_modified:", curation_concern.date_modified )
  395. # yaml_item( out, indent, ":description:", curation_concern.description, escape: true )
  396. # yaml_item( out, indent, ":depositor:", curation_concern.depositor )
  397. # yaml_item( out, indent, ":doi:", curation_concern.doi, escape: true )
  398. # yaml_item( out, indent, ":edit_users:", curation_concern.edit_users, escape: true )
  399. # yaml_item( out, indent, ':keyword:', curation_concern.keyword, escape: true )
  400. # yaml_item( out, indent, ":language:", curation_concern.language, escape: true )
  401. # yaml_item_prior_identifier( out, indent, curation_concern: curation_concern, source: source )
  402. # yaml_item_referenced_by( out, indent, curation_concern: curation_concern, source: source )
  403. # yaml_item_subject( out, indent, curation_concern: curation_concern, source: source )
  404. # yaml_item( out, indent, ':title:', curation_concern.title, escape: true )
  405. # yaml_item( out, indent, ":tombstone:", curation_concern.tombstone, single_value: true )
  406. # yaml_item( out, indent, ":total_work_count:", curation_concern.work_ids.count )
  407. # yaml_item( out, indent, ":total_file_size:", curation_concern.total_file_size )
  408. # yaml_item( out,
  409. # indent,
  410. # ":total_file_size_human_readable:",
  411. # human_readable_size( curation_concern.total_file_size ),
  412. # escape: true )
  413. # yaml_item( out, indent, ":visibility:", curation_concern.visibility )
  414. # end
  415. 1 def self.yaml_body_files( out,
  416. indent_base:,
  417. indent:,
  418. curation_concern:,
  419. mode: MODE_BUILD,
  420. source:,
  421. target_dirname: )
  422. indent_first_line = indent
  423. yaml_line( out, indent_first_line, ':file_set_ids:' )
  424. return unless curation_concern.file_sets.count.positive?
  425. indent = indent_base + indent_first_line + "-"
  426. curation_concern.file_sets.each do |file_set|
  427. yaml_item( out, indent, '', file_set.id, escape: true )
  428. end
  429. curation_concern.file_sets.each do |file_set|
  430. log_provenance_migrate( curation_concern: file_set, parent: curation_concern, source: source ) if MODE_MIGRATE == mode
  431. file_id = ":#{yaml_file_set_id( file_set )}:"
  432. yaml_line( out, indent_first_line, file_id )
  433. indent = indent_base + indent_first_line
  434. yaml_item( out, indent, ':id:', file_set.id, escape: true )
  435. single_value = 1 == file_set.title.size
  436. yaml_item( out, indent, ':title:', file_set.title, escape: true, single_value: single_value )
  437. yaml_item_prior_identifier( out, indent, curation_concern: file_set, source: source )
  438. file_path = yaml_export_file_path( target_dirname: target_dirname, file_set: file_set )
  439. yaml_item( out, indent, ':file_path:', file_path.to_s, escape: true )
  440. checksum = yaml_file_set_checksum( file_set: file_set )
  441. yaml_item( out, indent, ":checksum_algorithm:", checksum.present? ? checksum.algorithm : '', escape: true )
  442. yaml_item( out, indent, ":checksum_value:", checksum.present? ? checksum.value : '', escape: true )
  443. yaml_item( out, indent, ":edit_users:", file_set.edit_users, escape: true )
  444. file_size = if file_set.file_size.blank?
  445. file_set.original_file.nil? ? 0 : file_set.original_file.size
  446. else
  447. file_set.file_size[0]
  448. end
  449. yaml_item( out, indent, ":file_size:", file_size )
  450. yaml_item( out, indent, ":file_size_human_readable:", human_readable_size( file_size ), escape: true )
  451. yaml_item( out, indent, ":mime_type:", file_set.mime_type, escape: true )
  452. value = file_set.original_checksum.blank? ? '' : file_set.original_checksum[0]
  453. yaml_item( out, indent, ":original_checksum:", value )
  454. value = file_set.original_file.nil? ? nil : file_set.original_file.original_name
  455. yaml_item( out, indent, ":original_name:", value, escape: true )
  456. yaml_item( out, indent, ":visibility:", file_set.visibility )
  457. skip = %w[ title file_size ]
  458. attribute_names_file_set.each do |name|
  459. next if skip.include? name
  460. yaml_item_file_set( out, indent, file_set, name: name )
  461. end
  462. end
  463. end
  464. # def self.yaml_body_files2( out,
  465. # indent_base:,
  466. # indent:,
  467. # curation_concern:,
  468. # mode: MODE_BUILD,
  469. # source:,
  470. # target_dirname: )
  471. #
  472. # indent_first_line = indent
  473. # yaml_line( out, indent_first_line, ':file_set_ids:' )
  474. # return unless curation_concern.file_sets.count.positive?
  475. # indent = indent_base + indent_first_line + "-"
  476. # curation_concern.file_sets.each do |file_set|
  477. # yaml_item( out, indent, '', file_set.id, escape: true )
  478. # end
  479. # curation_concern.file_sets.each do |file_set|
  480. # log_provenance_migrate( curation_concern: file_set, parent: curation_concern, source: source ) if MODE_MIGRATE == mode
  481. # file_id = ":#{yaml_file_set_id( file_set )}:"
  482. # yaml_line( out, indent_first_line, file_id )
  483. # indent = indent_base + indent_first_line
  484. # yaml_item( out, indent, ':id:', file_set.id, escape: true )
  485. # single_value = 1 == file_set.title.size
  486. # yaml_item( out, indent, ':title:', file_set.title, escape: true, single_value: single_value )
  487. # yaml_item_prior_identifier( out, indent, curation_concern: file_set, source: source )
  488. # file_path = yaml_export_file_path( target_dirname: target_dirname, file_set: file_set )
  489. # yaml_item( out, indent, ':file_path:', file_path.to_s, escape: true )
  490. # checksum = yaml_file_set_checksum( file_set: file_set )
  491. # yaml_item( out, indent, ":checksum_algorithm:", checksum.present? ? checksum.algorithm : '', escape: true )
  492. # yaml_item( out, indent, ":checksum_value:", checksum.present? ? checksum.value : '', escape: true )
  493. # yaml_item( out, indent, ":date_created:", file_set.date_created )
  494. # yaml_item( out, indent, ":date_created:", file_set.date_created )
  495. # yaml_item( out, indent, ":date_modified:", file_set.date_modified )
  496. # yaml_item( out, indent, ":date_uploaded:", file_set.date_uploaded )
  497. # yaml_item( out, indent, ":edit_users:", file_set.edit_users, escape: true )
  498. # file_size = if file_set.file_size.blank?
  499. # file_set.original_file.nil? ? 0 : file_set.original_file.size
  500. # else
  501. # file_set.file_size[0]
  502. # end
  503. # yaml_item( out, indent, ":file_size:", file_size )
  504. # yaml_item( out, indent, ":file_size_human_readable:", human_readable_size( file_size ), escape: true )
  505. # yaml_item( out, indent, ":label:", file_set.label, escape: true )
  506. # yaml_item( out, indent, ":mime_type:", file_set.mime_type, escape: true )
  507. # value = file_set.original_checksum.blank? ? '' : file_set.original_checksum[0]
  508. # yaml_item( out, indent, ":original_checksum:", value )
  509. # value = file_set.original_file.nil? ? nil : file_set.original_file.original_name
  510. # yaml_item( out, indent, ":original_name:", value, escape: true )
  511. # yaml_item( out, indent, ":visibility:", file_set.visibility )
  512. # end
  513. # end
  514. 1 def self.yaml_body_user_body( out, indent_base:, indent:, user: )
  515. indent_first_line = indent
  516. user_email = ":#{yaml_user_email( user )}:"
  517. yaml_line( out, indent_first_line, user_email )
  518. indent = indent_base + indent_first_line
  519. yaml_item(out, indent, ':email:', user.email, escape: true )
  520. skip = %w[ email ]
  521. attribute_names_user.each do |name|
  522. next if skip.include? name
  523. yaml_item_user(out, indent, user, name: name )
  524. end
  525. end
  526. 1 def self.yaml_body_users( out, indent_base:, indent:, users: )
  527. yaml_item( out, indent, ":total_user_count:", users.count )
  528. indent_first_line = indent
  529. yaml_line( out, indent_first_line, ':user_emails:' )
  530. return unless users.count.positive?
  531. indent = indent_base + indent_first_line + "-"
  532. users.each do |user|
  533. yaml_item( out, indent, '', user.email, escape: true )
  534. end
  535. end
  536. 1 def self.yaml_body_works( out, indent:, curation_concern:, source: )
  537. yaml_item( out, indent, ":id:", curation_concern.id )
  538. yaml_item( out, indent, ":admin_set_id:", curation_concern.admin_set_id, escape: true )
  539. yaml_item( out, indent, ":edit_users:", curation_concern.edit_users, escape: true )
  540. yaml_item_prior_identifier( out, indent, curation_concern: curation_concern, source: source )
  541. yaml_item_rights( out, indent, curation_concern: curation_concern, source: source )
  542. yaml_item_subject( out, indent, curation_concern: curation_concern, source: source )
  543. yaml_item( out, indent, ":total_file_count:", curation_concern.file_set_ids.count )
  544. yaml_item( out, indent, ":total_file_size:", curation_concern.total_file_size )
  545. yaml_item( out,
  546. indent,
  547. ":total_file_size_human_readable:",
  548. human_readable_size( curation_concern.total_file_size ),
  549. escape: true )
  550. yaml_item( out, indent, ":visibility:", curation_concern.visibility )
  551. skip = %w[ prior_identifier rights rights_license subject subject_discipline total_file_size ]
  552. attribute_names_work( source: source ).each do |name|
  553. next if skip.include? name
  554. yaml_item_work( out, indent, curation_concern, name: name )
  555. end
  556. end
  557. # def self.yaml_body_works2( out, indent:, curation_concern:, source: )
  558. # yaml_item( out, indent, ":id:", curation_concern.id )
  559. # yaml_item( out, indent, ":admin_set_id:", curation_concern.admin_set_id, escape: true )
  560. # yaml_item( out, indent, ":authoremail:", curation_concern.authoremail )
  561. # yaml_item( out, indent, ":creator:", curation_concern.creator, escape: true )
  562. # yaml_item( out, indent, ":curation_notes_admin:", curation_concern.curation_notes_admin, escape: true ) if source == SOURCE_DBDv2
  563. # yaml_item( out, indent, ":curation_notes_user:", curation_concern.curation_notes_user, escape: true ) if source == SOURCE_DBDv2
  564. # yaml_item( out, indent, ":date_coverage:", curation_concern.date_coverage, single_value: true )
  565. # yaml_item( out, indent, ":date_created:", curation_concern.date_created )
  566. # yaml_item( out, indent, ":date_modified:", curation_concern.date_modified )
  567. # yaml_item( out, indent, ":date_uploaded:", curation_concern.date_uploaded )
  568. # yaml_item( out, indent, ":depositor:", curation_concern.depositor )
  569. # yaml_item( out, indent, ":description:", curation_concern.description, escape: true )
  570. # yaml_item( out, indent, ":doi:", curation_concern.doi, escape: true )
  571. # yaml_item( out, indent, ":edit_users:", curation_concern.edit_users, escape: true )
  572. # yaml_item( out, indent, ":fundedby:", curation_concern.fundedby, single_value: true, escape: true )
  573. # yaml_item( out, indent, ":fundedby_other:", curation_concern.fundedby_other, single_value: true, escape: true ) if source == SOURCE_DBDv2
  574. # yaml_item( out, indent, ":grantnumber:", curation_concern.grantnumber, escape: true )
  575. # yaml_item_referenced_by( out, indent, curation_concern: curation_concern, source: source )
  576. # yaml_item( out, indent, ':keyword:', curation_concern.keyword, escape: true )
  577. # yaml_item( out, indent, ":language:", curation_concern.language, escape: true )
  578. # yaml_item( out, indent, ":methodology:", curation_concern.methodology, escape: true )
  579. # yaml_item_prior_identifier( out, indent, curation_concern: curation_concern, source: source )
  580. # yaml_item_rights( out, indent, curation_concern: curation_concern, source: source )
  581. # yaml_item( out, indent, ":rights_license_other: ", curation_concern.rights_license_other, escape: true ) if source == SOURCE_DBDv2
  582. # yaml_item_subject( out, indent, curation_concern: curation_concern, source: source )
  583. # yaml_item( out, indent, ':title:', curation_concern.title, escape: true )
  584. # yaml_item( out, indent, ":tombstone:", curation_concern.tombstone, single_value: true )
  585. # yaml_item( out, indent, ":total_file_count:", curation_concern.file_set_ids.count )
  586. # yaml_item( out, indent, ":total_file_size:", curation_concern.total_file_size )
  587. # yaml_item( out,
  588. # indent,
  589. # ":total_file_size_human_readable:",
  590. # human_readable_size( curation_concern.total_file_size ),
  591. # escape: true )
  592. # yaml_item( out, indent, ":visibility:", curation_concern.visibility )
  593. # end
  594. 1 def self.yaml_escape_value( value, comment: false, escape: false )
  595. return "" if value.nil?
  596. return value unless escape
  597. return value if comment
  598. value = value.to_json
  599. return "" if "\"\"" == value
  600. return value
  601. end
  602. 1 def self.yaml_export_file_path( target_dirname:, file_set: )
  603. file = file_from_file_set( file_set )
  604. export_file_name = file.original_name
  605. target_dirname.join "#{file_set.id}_#{export_file_name}"
  606. end
  607. 1 def self.yaml_file_set_checksum( file_set: )
  608. file = file_from_file_set( file_set )
  609. return file.checksum if file.present?
  610. return nil
  611. end
  612. 1 def self.yaml_file_set_id( file_set )
  613. "f_#{file_set.id}"
  614. end
  615. 1 def self.yaml_filename( pathname_dir:, id:, prefix:, task: )
  616. pathname_dir = Pathname.new pathname_dir unless pathname_dir.is_a? Pathname
  617. pathname_dir.join "#{prefix}#{id}_#{task}.yml"
  618. end
  619. 1 def self.yaml_filename_collection( pathname_dir:, collection:, task: DEFAULT_TASK )
  620. yaml_filename( pathname_dir: pathname_dir, id: collection.id, prefix: PREFIX_COLLECTION, task: task )
  621. end
  622. 1 def self.yaml_filename_users( pathname_dir:, task: DEFAULT_TASK )
  623. yaml_filename( pathname_dir: pathname_dir, id: '', prefix: PREFIX_USERS, task: task )
  624. end
  625. 1 def self.yaml_filename_work( pathname_dir:, work:, task: DEFAULT_TASK )
  626. yaml_filename( pathname_dir: pathname_dir, id: work.id, prefix: PREFIX_WORK, task: task )
  627. end
  628. 1 def self.yaml_header( out, indent:, curation_concern:, header_type:, source:, mode: )
  629. yaml_line( out, indent, ':email:', curation_concern.depositor )
  630. yaml_line( out, indent, ':visibility:', curation_concern.visibility )
  631. yaml_line( out, indent, ':ingester:', '' )
  632. yaml_line( out, indent, ':source:', source )
  633. yaml_line( out, indent, ':export_timestamp:', DateTime.now.to_s )
  634. yaml_line( out, indent, ':mode:', mode )
  635. yaml_line( out, indent, ':id:', curation_concern.id )
  636. yaml_line( out, indent, header_type )
  637. end
  638. 1 def self.yaml_header_populate( out, indent:, rake_task: 'umrdr:populate', target_filename: )
  639. yaml_line( out, indent, target_filename.to_s, comment: true )
  640. yaml_line( out, indent, "bundle exec rake #{rake_task}[#{target_filename}]", comment: true )
  641. yaml_line( out, indent, "---" )
  642. yaml_line( out, indent, ':user:' )
  643. end
  644. 1 def self.yaml_header_users( out, indent:, header_type: HEADER_TYPE_USERS, source:, mode: )
  645. yaml_line( out, indent, ':ingester:', '' )
  646. yaml_line( out, indent, ':source:', source )
  647. yaml_line( out, indent, ':export_timestamp:', DateTime.now.to_s )
  648. yaml_line( out, indent, ':mode:', mode )
  649. yaml_line( out, indent, header_type )
  650. end
  651. 1 def self.yaml_is_a_work?( curation_concern:, source: )
  652. if source == SOURCE_DBDv2
  653. curation_concern.is_a? DataSet
  654. else
  655. curation_concern.is_a? GenericWork
  656. end
  657. end
  658. 1 def self.yaml_item( out,
  659. indent,
  660. label,
  661. value = '',
  662. single_value: false,
  663. comment: false,
  664. indent_base: " ",
  665. label_postfix: ' ',
  666. escape: false )
  667. indent = "# #{indent}" if comment
  668. if single_value && value.present? && value.respond_to?( :each )
  669. value = value[0]
  670. out.puts "#{indent}#{label}#{label_postfix}#{yaml_escape_value( value, comment: comment, escape: escape )}"
  671. elsif value.respond_to?(:each)
  672. out.puts "#{indent}#{label}#{label_postfix}"
  673. indent += indent_base
  674. value.each { |item| out.puts "#{indent}- #{yaml_escape_value( item, comment: comment, escape: escape )}" }
  675. else
  676. out.puts "#{indent}#{label}#{label_postfix}#{yaml_escape_value( value, comment: comment, escape: escape )}"
  677. end
  678. end
  679. 1 def self.yaml_item_collection( out, indent, curation_concern, name: )
  680. return if ATTRIBUTE_NAMES_IGNORE.include? name
  681. label = ":#{name}:"
  682. value = curation_concern[name]
  683. return if value.blank? && !ATTRIBUTE_NAMES_ALWAYS_INCLUDE_CC.include?( name )
  684. yaml_item( out, indent, label, value, escape: true )
  685. end
  686. 1 def self.yaml_item_file_set( out, indent, file_set, name: )
  687. return if ATTRIBUTE_NAMES_IGNORE.include? name
  688. label = ":#{name}:"
  689. value = file_set[name]
  690. return if value.blank? && !ATTRIBUTE_NAMES_ALWAYS_INCLUDE_FILE_SET.include?( name )
  691. yaml_item( out, indent, label, value, escape: true )
  692. end
  693. 1 def self.yaml_item_prior_identifier( out, indent, curation_concern:, source: )
  694. if source == SOURCE_DBDv1
  695. yaml_item( out, indent, ":prior_identifier:", '' )
  696. else
  697. # ids = curation_concern.prior_identifier
  698. # ids = [] if ids.nil?
  699. # ids << curation_concern.id
  700. # yaml_item( out, indent, ':prior_identifier:', ActiveSupport::JSON.encode( ids ) )
  701. yaml_item( out, indent, ":prior_identifier:", curation_concern.prior_identifier )
  702. end
  703. end
  704. 1 def self.yaml_item_referenced_by( out, indent, curation_concern:, source: )
  705. if source == SOURCE_DBDv1
  706. yaml_item( out, indent, ":isReferencedBy:", curation_concern.isReferencedBy, escape: true )
  707. else
  708. yaml_item( out, indent, ":referenced_by:", curation_concern.referenced_by, escape: true )
  709. end
  710. end
  711. 1 def self.yaml_item_rights( out, indent, curation_concern:, source: )
  712. if source == SOURCE_DBDv1
  713. yaml_item( out, indent, ":rights:", curation_concern.rights, escape: true )
  714. else
  715. yaml_item( out, indent, ":rights_license:", curation_concern.rights_license, escape: true )
  716. end
  717. end
  718. 1 def self.yaml_item_subject( out, indent, curation_concern:, source: )
  719. if source == SOURCE_DBDv1
  720. yaml_item( out, indent, ":subject:", curation_concern.subject, escape: true )
  721. else
  722. yaml_item( out, indent, ":subject_discipline:", curation_concern.subject_discipline, escape: true )
  723. end
  724. end
  725. 1 def self.yaml_item_user( out, indent, user, name: )
  726. return if ATTRIBUTE_NAMES_USER_IGNORE.include? name
  727. label = ":#{name}:"
  728. value = user[name]
  729. return if value.blank? && !ATTRIBUTE_NAMES_ALWAYS_INCLUDE_USER.include?( name )
  730. yaml_item( out, indent, label, value, escape: true )
  731. end
  732. 1 def self.yaml_item_work( out, indent, curation_concern, name: )
  733. return if ATTRIBUTE_NAMES_IGNORE.include? name
  734. label = ":#{name}:"
  735. value = curation_concern[name]
  736. return if value.blank? && !ATTRIBUTE_NAMES_ALWAYS_INCLUDE_CC.include?( name )
  737. yaml_item( out, indent, label, value, escape: true )
  738. end
  739. 1 def self.yaml_line( out, indent, label, value = '', comment: false, label_postfix: ' ', escape: false )
  740. indent = "# #{indent}" if comment
  741. out.puts "#{indent}#{label}#{label_postfix}#{yaml_escape_value( value, comment: comment, escape: escape )}"
  742. end
  743. 1 def self.yaml_populate_collection( collection:,
  744. dir: DEFAULT_BASE_DIR,
  745. out: nil,
  746. populate_works: true,
  747. export_files: true,
  748. overwrite_export_files: true,
  749. source: DEFAULT_SOURCE,
  750. mode: MODE_BUILD,
  751. target_filename: nil,
  752. target_dirname: nil )
  753. target_file = nil
  754. dir = Pathname.new dir unless dir.is_a? Pathname
  755. if out.nil?
  756. collection = Collection.find collection if collection.is_a? String
  757. target_file = yaml_filename_collection( pathname_dir: dir, collection: collection )
  758. target_dir = yaml_targetdir_collection( pathname_dir: dir, collection: collection )
  759. Dir.mkdir( target_dir ) unless Dir.exist? target_dir
  760. open( target_file, 'w' ) do |out2|
  761. yaml_populate_collection( collection: collection,
  762. out: out2,
  763. populate_works: populate_works,
  764. export_files: false,
  765. overwrite_export_files: overwrite_export_files,
  766. source: source,
  767. mode: mode,
  768. target_filename: target_file,
  769. target_dirname: target_dir )
  770. end
  771. if export_files
  772. collection.member_objects.each do |work|
  773. next unless yaml_is_a_work?( curation_concern: work, source: source )
  774. yaml_work_export_files( work: work, target_dirname: target_dir, overwrite: overwrite_export_files )
  775. end
  776. end
  777. else
  778. log_provenance_migrate( curation_concern: collection, source: source ) if MODE_MIGRATE == mode
  779. indent_base = " " * 2
  780. indent = indent_base * 0
  781. yaml_header_populate( out, indent: indent, target_filename: target_filename )
  782. indent = indent_base * 1
  783. yaml_header( out,
  784. indent: indent,
  785. curation_concern: collection,
  786. header_type: HEADER_TYPE_COLLECTIONS,
  787. source: source,
  788. mode: mode )
  789. indent = indent_base * 2
  790. yaml_body_collections( out, indent: indent, curation_concern: collection, source: source )
  791. return unless populate_works
  792. return unless collection.member_objects.size.positive?
  793. indent = indent_base * 2
  794. yaml_line( out, indent, HEADER_TYPE_WORKS )
  795. indent = indent_base + indent + "-"
  796. collection.member_objects.each do |work|
  797. next unless yaml_is_a_work?( curation_concern: work, source: source )
  798. yaml_item( out, indent, '', work.id, escape: true )
  799. end
  800. indent = indent_base * 2
  801. collection.member_objects.each do |work|
  802. next unless yaml_is_a_work?( curation_concern: work, source: source )
  803. indent = indent_base * 2
  804. yaml_line( out, indent, ":works_#{work.id}:" )
  805. indent = indent_base * 3
  806. log_provenance_migrate( curation_concern: work, parent: collection, source: source ) if MODE_MIGRATE == mode
  807. yaml_body_works( out, indent: indent, curation_concern: work, source: source )
  808. yaml_body_files( out,
  809. indent_base: indent_base,
  810. indent: indent,
  811. curation_concern: work,
  812. mode: mode,
  813. source: source,
  814. target_dirname: target_dirname )
  815. end
  816. end
  817. end
  818. 1 def self.yaml_populate_users( dir: DEFAULT_BASE_DIR,
  819. out: nil,
  820. source: DEFAULT_SOURCE,
  821. mode: MODE_MIGRATE,
  822. target_filename: nil )
  823. target_file = nil
  824. dir = Pathname.new dir unless dir.is_a? Pathname
  825. Dir.mkdir( dir ) unless Dir.exist? dir
  826. if out.nil?
  827. target_file = yaml_filename_users( pathname_dir: dir, task: mode )
  828. # target_dir = yaml_targetdir_users( pathname_dir: dir, task: mode )
  829. # Dir.mkdir( target_dir ) unless Dir.exist? target_dir
  830. open( target_file, 'w' ) do |out2|
  831. yaml_populate_users( out: out2, source: source, mode: mode, target_filename: target_file )
  832. end
  833. else
  834. # log_provenance_migrate( curation_concern: curation_concern, source: source ) if MODE_MIGRATE == mode
  835. indent_base = " " * 2
  836. indent = indent_base * 0
  837. yaml_header_populate( out, indent: indent, rake_task: 'umrdr:populate_users', target_filename: target_filename )
  838. indent = indent_base * 1
  839. yaml_header_users( out, indent: indent, source: source, mode: mode )
  840. indent = indent_base * 2
  841. users = User.all
  842. yaml_body_users( out, indent_base: indent_base, indent: indent, users: users )
  843. users.each do |user|
  844. yaml_body_user_body( out, indent_base: indent_base, indent: indent, user: user )
  845. end
  846. end
  847. return target_file
  848. end
  849. 1 def self.yaml_populate_work( curation_concern:,
  850. dir: DEFAULT_BASE_DIR,
  851. out: nil,
  852. export_files: true,
  853. overwrite_export_files: true,
  854. source: DEFAULT_SOURCE,
  855. mode: MODE_BUILD,
  856. target_filename: nil,
  857. target_dirname: nil )
  858. target_file = nil
  859. dir = Pathname.new dir unless dir.is_a? Pathname
  860. if out.nil?
  861. curation_concern = yaml_work_find( curation_concern: curation_concern, source: source ) if curation_concern.is_a? String
  862. target_file = yaml_filename_work( pathname_dir: dir, work: curation_concern )
  863. target_dir = yaml_targetdir_work( pathname_dir: dir, work: curation_concern )
  864. Dir.mkdir( target_dir ) unless Dir.exist? target_dir
  865. open( target_file, 'w' ) do |out2|
  866. yaml_populate_work( curation_concern: curation_concern,
  867. out: out2,
  868. export_files: export_files,
  869. overwrite_export_files: overwrite_export_files,
  870. source: source,
  871. mode: mode,
  872. target_filename: target_file,
  873. target_dirname: target_dir )
  874. end
  875. if export_files
  876. yaml_work_export_files( work: curation_concern, target_dirname: target_dir, overwrite: overwrite_export_files )
  877. end
  878. else
  879. log_provenance_migrate( curation_concern: curation_concern, source: source ) if MODE_MIGRATE == mode
  880. indent_base = " " * 2
  881. indent = indent_base * 0
  882. yaml_header_populate( out, indent: indent, target_filename: target_filename )
  883. indent = indent_base * 1
  884. yaml_header( out,
  885. indent: indent,
  886. curation_concern: curation_concern,
  887. header_type: HEADER_TYPE_WORKS,
  888. source: source,
  889. mode: mode )
  890. indent = indent_base * 2
  891. yaml_body_works( out, indent: indent, curation_concern: curation_concern, source: source )
  892. yaml_body_files( out,
  893. indent_base: indent_base,
  894. indent: indent,
  895. curation_concern: curation_concern,
  896. mode: mode,
  897. source: source,
  898. target_dirname: target_dirname )
  899. end
  900. return target_file
  901. end
  902. 1 def self.yaml_targetdir( pathname_dir:, id:, prefix:, task: )
  903. pathname_dir = Pathname.new pathname_dir unless pathname_dir.is_a? Pathname
  904. pathname_dir.join "#{prefix}#{id}_#{task}"
  905. end
  906. 1 def self.yaml_targetdir_collection( pathname_dir:, collection:, task: DEFAULT_TASK )
  907. yaml_targetdir( pathname_dir: pathname_dir, id: collection.id, prefix: PREFIX_COLLECTION, task: task )
  908. end
  909. 1 def self.yaml_targetdir_users( pathname_dir:, task: DEFAULT_TASK )
  910. yaml_targetdir( pathname_dir: pathname_dir, id: '', prefix: PREFIX_USERS, task: task )
  911. end
  912. 1 def self.yaml_targetdir_work( pathname_dir:, work:, task: DEFAULT_TASK )
  913. yaml_targetdir( pathname_dir: pathname_dir, id: work.id, prefix: PREFIX_WORK, task: task )
  914. end
  915. 1 def self.yaml_user_email( user )
  916. "user_#{user.email}"
  917. end
  918. 1 def self.yaml_work_export_files( work:, target_dirname: nil, log_filename: nil, overwrite: true )
  919. log_file = target_dirname.join ".export.log" if log_filename.nil?
  920. open( log_file, 'w' ) { |f| f.write('') } # erase log file
  921. start_time = Time.now
  922. log_lines( log_file,
  923. "Starting yaml work export of files at #{start_time} ...",
  924. "Generic work id: #{work.id}",
  925. "Total file count: #{work.file_sets.count}")
  926. total_byte_count = 0
  927. if work.file_sets.count.positive?
  928. work.file_sets.each do |file_set|
  929. export_file_name = yaml_export_file_path( target_dirname: target_dirname, file_set: file_set )
  930. write_file = if overwrite
  931. true
  932. else
  933. !File.exist?( export_file_name )
  934. end
  935. file = file_from_file_set( file_set )
  936. export_what = "#{export_file_name} (#{human_readable_size(file.size)} / #{file.size} bytes)"
  937. if write_file
  938. source_uri = file.uri.value
  939. log_lines( log_file, "Starting file export of #{export_what} at #{Time.now}." )
  940. bytes_copied = ExportFilesHelper.export_file_uri( source_uri: source_uri, target_file: export_file_name )
  941. total_byte_count += bytes_copied
  942. log_lines( log_file, "Finished file export of #{export_what} at #{Time.now}." )
  943. else
  944. log_lines( log_file, "Skipping file export of #{export_what} at #{Time.now}." )
  945. end
  946. end
  947. end
  948. end_time = Time.now
  949. log_lines( log_file,
  950. "Total bytes exported: #{total_byte_count} (#{human_readable_size(total_byte_count)})",
  951. "... finished yaml generic work export of files at #{end_time}.")
  952. rescue Exception => e # rubocop:disable Lint/RescueException
  953. # rubocop:disable Rails/Output
  954. puts "#{e.class}: #{e.message} at #{e.backtrace.join("\n")}"
  955. # rubocop:enable Rails/Output
  956. end
  957. 1 def self.yaml_work_find( curation_concern:, source: )
  958. if source == SOURCE_DBDv2
  959. DataSet.find curation_concern
  960. else
  961. GenericWork.find curation_concern
  962. end
  963. end
  964. end
  965. end

app/helpers/deepblue/ordered_string_helper.rb

90.91% lines covered

11 relevant lines. 10 lines covered and 1 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 module OrderedStringHelper
  4. 1 class DeserializeError < RuntimeError
  5. end
  6. #
  7. # convert a serialized array to a normal array of values
  8. # assumes values are stored as json converted to strings
  9. # a failure to deserialize throws a DeserializeError,
  10. # the exact reason for failure is ignored
  11. #
  12. 1 def self.deserialize( serialized_string_containing_an_array )
  13. 467 if serialized_string_containing_an_array.start_with?('[')
  14. begin
  15. 467 arr = ActiveSupport::JSON.decode serialized_string_containing_an_array
  16. 467 return arr if arr.is_a?( Array )
  17. rescue ActiveSupport::JSON.parse_error # rubocop:disable Lint/HandleExceptions
  18. # ignore and fall through
  19. end
  20. end
  21. raise OrderedStringHelper::DeserializeError
  22. end
  23. #
  24. # serialize a normal array of values to an array of ordered values
  25. #
  26. 1 def self.serialize( arr )
  27. 88 serialized_string_containing_an_array = ActiveSupport::JSON.encode( arr ).to_s
  28. 88 return serialized_string_containing_an_array
  29. end
  30. end
  31. end

app/helpers/deepblue/provenance_helper.rb

92.86% lines covered

14 relevant lines. 13 lines covered and 1 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 module ProvenanceHelper
  4. 1 extend JsonLoggerHelper
  5. 1 extend JsonLoggerHelper::ClassMethods
  6. # rubocop:disable Style/ClassVars
  7. 1 def self.echo_to_rails_logger
  8. 5 @@echo_to_rails_logger ||= DeepBlueDocs::Application.config.provenance_log_echo_to_rails_logger
  9. end
  10. 1 def self.echo_to_rails_logger=( echo_to_rails_logger )
  11. @@echo_to_rails_logger = echo_to_rails_logger
  12. end
  13. # rubocop:enable Style/ClassVars
  14. 1 def self.log( class_name: 'UnknownClass',
  15. event: 'unknown',
  16. event_note: '',
  17. id: 'unknown_id',
  18. timestamp: timestamp_now,
  19. time_zone: timestamp_zone,
  20. echo_to_rails_logger: ProvenanceHelper.echo_to_rails_logger,
  21. **log_key_values )
  22. 4 msg = msg_to_log( class_name: class_name,
  23. event: event,
  24. event_note: event_note,
  25. id: id,
  26. timestamp: timestamp,
  27. time_zone: time_zone,
  28. **log_key_values )
  29. 4 log_raw msg
  30. 4 Rails.logger.info msg if echo_to_rails_logger
  31. end
  32. 1 def self.log_raw( msg )
  33. 5 PROV_LOGGER.info( msg )
  34. end
  35. end
  36. end

app/helpers/deepblue/scheduler_helper.rb

60.0% lines covered

15 relevant lines. 9 lines covered and 6 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 require './lib/scheduler_logger'
  4. 1 module SchedulerHelper
  5. 1 extend JsonLoggerHelper
  6. 1 extend JsonLoggerHelper::ClassMethods
  7. # rubocop:disable Style/ClassVars
  8. 1 def self.echo_to_rails_logger
  9. @@echo_to_rails_logger ||= DeepBlueDocs::Application.config.scheduler_log_echo_to_rails_logger
  10. end
  11. 1 def self.echo_to_rails_logger=( echo_to_rails_logger )
  12. @@echo_to_rails_logger = echo_to_rails_logger
  13. end
  14. # rubocop:enable Style/ClassVars
  15. 1 def self.log( class_name: 'UnknownClass',
  16. event: 'unknown',
  17. event_note: '',
  18. id: '',
  19. timestamp: timestamp_now,
  20. echo_to_rails_logger: SchedulerHelper.echo_to_rails_logger,
  21. **log_key_values )
  22. msg = msg_to_log( class_name: class_name,
  23. event: event,
  24. event_note: event_note,
  25. id: id,
  26. timestamp: timestamp,
  27. time_zone: LoggingHelper.timestamp_zone,
  28. **log_key_values )
  29. log_raw msg
  30. Rails.logger.info msg if echo_to_rails_logger
  31. end
  32. 1 def self.log_raw( msg )
  33. SCHEDULER_LOGGER.info( msg )
  34. end
  35. end
  36. end

app/helpers/deepblue/upload_helper.rb

54.55% lines covered

22 relevant lines. 12 lines covered and 10 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 require './lib/upload_logger'
  4. 1 module UploadHelper
  5. 1 extend JsonLoggerHelper
  6. 1 extend JsonLoggerHelper::ClassMethods
  7. # rubocop:disable Style/ClassVars
  8. 1 def self.echo_to_rails_logger
  9. @@echo_to_rails_logger ||= DeepBlueDocs::Application.config.upload_log_echo_to_rails_logger
  10. end
  11. 1 def self.echo_to_rails_logger=( echo_to_rails_logger )
  12. @@echo_to_rails_logger = echo_to_rails_logger
  13. end
  14. # rubocop:enable Style/ClassVars
  15. 1 def self.log( class_name: 'UnknownClass',
  16. event: 'unknown',
  17. event_note: '',
  18. id: 'unknown_id',
  19. timestamp: timestamp_now,
  20. echo_to_rails_logger: UploadHelper.echo_to_rails_logger,
  21. **log_key_values )
  22. msg = msg_to_log( class_name: class_name,
  23. event: event,
  24. event_note: event_note,
  25. id: id,
  26. timestamp: timestamp,
  27. time_zone: LoggingHelper.timestamp_zone,
  28. **log_key_values )
  29. log_raw msg
  30. Rails.logger.info msg if echo_to_rails_logger
  31. end
  32. 1 def self.log_raw( msg )
  33. UPLOAD_LOGGER.info( msg )
  34. end
  35. 1 def self.uploaded_file_id( uploaded_file )
  36. return nil unless uploaded_file.respond_to? :id
  37. uploaded_file.id
  38. end
  39. 1 def self.uploaded_file_path( uploaded_file )
  40. uploaded_file.file.path
  41. end
  42. 1 def self.uploaded_file_size( uploaded_file )
  43. File.size uploaded_file.file.path
  44. end
  45. end
  46. end

app/helpers/deepblue_helper.rb

10.42% lines covered

48 relevant lines. 5 lines covered and 43 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module DeepblueHelper
  3. 1 def self.display_timestamp( timestamp )
  4. timestamp = timestamp.to_datetime if timestamp.is_a? Time
  5. timestamp = DateTime.parse timestamp if timestamp.is_a? String
  6. if DeepBlueDocs::Application.config.datetime_stamp_display_local_time_zone
  7. timestamp = timestamp.new_offset( DeepBlueDocs::Application.config.timezone_offset )
  8. "#{timestamp.strftime("%Y-%m-%d %H:%M:%S")}"
  9. else
  10. "#{timestamp.strftime("%Y-%m-%d %H:%M:%S")} #{timestamp.formatted_offset(false, 'UTC')}"
  11. end
  12. end
  13. 1 def self.human_readable_size( value, precision: 3 )
  14. ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert( value, precision: precision )
  15. end
  16. 1 def user_agent()
  17. user_agent = request.env['HTTP_USER_AGENT']
  18. user_agent
  19. end
  20. 1 def users_browser()
  21. user_agent = user_agent().downcase
  22. @users_browser ||= begin
  23. if user_agent.index('msie') && !user_agent.index('opera') && !user_agent.index('webtv')
  24. # 'ie'+user_agent[user_agent.index('msie')+5].chr
  25. 'msie'
  26. elsif user_agent.index('gecko/')
  27. 'gecko'
  28. elsif user_agent.index('opera')
  29. 'opera'
  30. elsif user_agent.index('konqueror')
  31. 'konqueror'
  32. elsif user_agent.index('ipod')
  33. 'ipod'
  34. elsif user_agent.index('ipad')
  35. 'ipad'
  36. elsif user_agent.index('iphone')
  37. 'iphone'
  38. elsif user_agent.index('chrome/')
  39. 'chrome'
  40. elsif user_agent.index('applewebkit/')
  41. 'safari'
  42. elsif user_agent.index('googlebot/')
  43. 'googlebot'
  44. elsif user_agent.index('msnbot')
  45. 'msnbot'
  46. elsif user_agent.index('yahoo! slurp')
  47. 'yahoobot'
  48. elsif user_agent.index('mozilla/5.0 (windows nt 6.3; win64, x64')
  49. 'msie'
  50. elsif user_agent.index('mozilla/5.0 (windows nt 10.0; win64; x64)')
  51. 'msie'
  52. #Everything thinks it's mozilla, so this goes last
  53. elsif user_agent.index('mozilla/')
  54. 'gecko'
  55. else
  56. 'unknown'
  57. end
  58. end
  59. return @users_browser
  60. end
  61. end

app/helpers/hyrax/ability_helper.rb

30.43% lines covered

23 relevant lines. 7 lines covered and 16 lines missed.
    
  1. 1 module Hyrax
  2. 1 module AbilityHelper
  3. 1 def visibility_options(variant)
  4. options = [
  5. Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC,
  6. Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED,
  7. Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
  8. ]
  9. case variant
  10. when :restrict
  11. options.delete_at(0)
  12. options.delete_at(0)
  13. options.reverse!
  14. when :loosen
  15. options.delete_at(1)
  16. options.delete_at(1)
  17. end
  18. options.map { |value| [visibility_text(value), value] }
  19. end
  20. 1 def visibility_badge(value)
  21. PermissionBadge.new(value).render
  22. end
  23. 1 def render_visibility_link(document)
  24. # Admin Sets do not have a visibility property.
  25. return if document.respond_to?(:admin_set?) && document.admin_set?
  26. # Anchor must match with a tab in
  27. # https://github.com/samvera/hyrax/blob/master/app/views/hyrax/base/_guts4form.html.erb#L2
  28. path = if document.collection?
  29. hyrax.edit_dashboard_collection_path(document, anchor: 'share')
  30. else
  31. edit_polymorphic_path([main_app, document], anchor: 'share')
  32. end
  33. link_to(
  34. visibility_badge(document.visibility),
  35. path,
  36. id: "permission_#{document.id}",
  37. class: 'visibility-link'
  38. )
  39. end
  40. 1 private
  41. 1 def visibility_text(value)
  42. return institution_name if value == Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED
  43. t("hyrax.visibility.#{value}.text")
  44. end
  45. end
  46. end

app/helpers/hyrax/branding_helper.rb

22.03% lines covered

59 relevant lines. 13 lines covered and 46 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 module BrandingHelper
  4. 1 def branding_banner_file( id: )
  5. # Find Banner filename
  6. ci = CollectionBrandingInfo.where( collection_id: id, role: "banner" )
  7. brand_path( collection_branding_info: ci[0] ) unless ci.empty?
  8. end
  9. 1 def branding_logo_record( id: )
  10. logo_info = []
  11. # Find Logo filename, alttext, linktext
  12. cis = CollectionBrandingInfo.where( collection_id: id, role: "logo" )
  13. return if cis.empty?
  14. cis.each do |coll_info|
  15. logo_file = File.split(coll_info.local_path).last
  16. file_location = brand_path( collection_branding_info: coll_info ) unless logo_file.empty?
  17. alttext = coll_info.alt_text
  18. linkurl = coll_info.target_url
  19. logo_info << { file: logo_file, file_location: file_location, alttext: alttext, linkurl: linkurl }
  20. end
  21. logo_info
  22. end
  23. 1 def brand_path( collection_branding_info: )
  24. rv = collection_branding_info
  25. local_path = collection_branding_info.local_path
  26. return rv if local_path.blank?
  27. local_path_relative = local_path.split("/")[-4..-1].join('/')
  28. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  29. ::Deepblue::LoggingHelper.called_from,
  30. "collection_branding_info = #{collection_branding_info}",
  31. "local_path = #{local_path}",
  32. "local_path_relative=#{local_path_relative}",
  33. "" ]
  34. rv = ::DeepBlueDocs::Application.config.relative_url_root + "/" + local_path_relative
  35. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  36. ::Deepblue::LoggingHelper.called_from,
  37. "rv = #{rv}",
  38. "" ]
  39. return rv
  40. end
  41. 1 def branding_banner_info( id: )
  42. @banner_info ||= begin
  43. # Find Banner filename
  44. banner_info = collection_banner_info( id: id )
  45. banner_file = File.split(banner_info.first.local_path).last unless banner_info.empty?
  46. file_location = banner_info.first.local_path unless banner_info.empty?
  47. relative_path = brand_path( collection_branding_info: banner_info.first ) unless banner_info.empty?
  48. { file: banner_file, full_path: file_location, relative_path: relative_path }
  49. end
  50. end
  51. 1 def branding_logo_info( id: )
  52. @logo_info ||= begin
  53. # Find Logo filename, alttext, linktext
  54. logos_info = collection_logo_info( id: id )
  55. logos_info.map do |logo_info|
  56. logo_file = File.split(logo_info.local_path).last
  57. relative_path = brand_path( collection_branding_info: logo_info ) unless logo_file.empty?
  58. alttext = logo_info.alt_text
  59. linkurl = logo_info.target_url
  60. { file: logo_file, full_path: logo_info.local_path, relative_path: relative_path, alttext: alttext, linkurl: linkurl }
  61. end
  62. end
  63. end
  64. 1 def collection_banner_info( id: )
  65. CollectionBrandingInfo.where( collection_id: id.to_s ).where( role: "banner" )
  66. end
  67. 1 def collection_logo_info( id: )
  68. CollectionBrandingInfo.where( collection_id: id.to_s ).where( role: "logo" )
  69. end
  70. 1 def branding_file_save( collection_branding_info:, file_location:, copy_file: true )
  71. local_dir = branding_file_find_local_dir_name( collection_id: collection_id, role: role )
  72. FileUtils.mkdir_p local_dir
  73. local_path = collection_branding_info.local_path
  74. FileUtils.cp file_location, local_path unless file_location == local_path || !copy_file
  75. FileUtils.remove_file(file_location) if File.exist?(file_location) && copy_file
  76. super()
  77. end
  78. 1 def branding_file_delete( location_path: )
  79. FileUtils.remove_file( location_path ) if File.exist?( location_path )
  80. end
  81. 1 def branding_file_find_local_filename( collection_id:, role:, filename: )
  82. local_dir = branding_file_find_local_dir_name( collection_id: collection_id, role: role )
  83. File.join(local_dir, filename)
  84. end
  85. 1 def branding_file_find_local_dir_name( collection_id:, role: )
  86. File.join( Hyrax.config.branding_path, collection_id.to_s, role.to_s)
  87. end
  88. end
  89. end

app/helpers/hyrax/embargo_helper.rb

19.19% lines covered

99 relevant lines. 19 lines covered and 80 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 module EmbargoHelper
  4. 1 def asset_embargo_release_date( asset: )
  5. rv = "#{asset.embargo_release_date} #{Time.zone}"
  6. DateTime.parse rv
  7. end
  8. 1 def assets_with_expired_embargoes
  9. 3 ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  10. ::Deepblue::LoggingHelper.called_from,
  11. "" ]
  12. 3 @assets_with_expired_embargoes ||= EmbargoService.assets_with_expired_embargoes
  13. end
  14. 1 def assets_under_embargo
  15. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  16. ::Deepblue::LoggingHelper.called_from,
  17. "" ]
  18. @assets_under_embargo ||= EmbargoService.assets_under_embargo
  19. end
  20. 1 def assets_with_deactivated_embargoes
  21. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  22. ::Deepblue::LoggingHelper.called_from,
  23. "" ]
  24. @assets_with_deactivated_embargoes ||= EmbargoService.assets_with_deactivated_embargoes
  25. end
  26. 1 def about_to_expire_embargo_email( asset:, expiration_days:, email_owner: true, test_mode: false, verbose: false )
  27. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  28. ::Deepblue::LoggingHelper.called_from,
  29. ::Deepblue::LoggingHelper.obj_class( "asset", asset ),
  30. "asset=#{asset}",
  31. "expiration_days=#{expiration_days}",
  32. "email_owner=#{email_owner}",
  33. "test_mode=#{test_mode}",
  34. "verbose=#{verbose}",
  35. "" ]
  36. embargo_release_date = asset.embargo_release_date
  37. curation_concern = ::ActiveFedora::Base.find asset.id
  38. id = curation_concern.id
  39. title = curation_concern.title.join
  40. subject = ::Deepblue::EmailHelper.t( "hyrax.email.about_to_expire_embargo.subject", expiration_days: expiration_days, title: title )
  41. visibility = visibility_on_embargo_deactivation( curation_concern: curation_concern )
  42. url = ::Deepblue::EmailHelper.curation_concern_url( curation_concern: curation_concern )
  43. email = curation_concern.authoremail
  44. ::Deepblue::LoggingHelper.debug "about_to_expire_embargo_email: curation concern id: #{id} email: #{email} exipration_days: #{expiration_days}" if verbose
  45. body = []
  46. body << ::Deepblue::EmailHelper.t( "hyrax.email.about_to_expire_embargo.for",
  47. expiration_days: expiration_days,
  48. embargo_release_date: embargo_release_date,
  49. title: title,
  50. id: id )
  51. body << ::Deepblue::EmailHelper.t( "hyrax.email.about_to_expire_embargo.visibility", visibility: visibility )
  52. body << ::Deepblue::EmailHelper.t( "hyrax.email.about_to_expire_embargo.visit", url: url )
  53. body = body.join( '' )
  54. event_note = "#{expiration_days} days"
  55. event_note += " test_mode" if test_mode
  56. ::Deepblue::EmailHelper.log( class_name: self.class.name,
  57. current_user: nil,
  58. event: "Embargo expiration notification",
  59. event_note: event_note,
  60. id: id,
  61. to: email,
  62. from: email,
  63. subject: subject,
  64. body: body )
  65. ::Deepblue::EmailHelper.send_email( to: email, from: email, subject: subject, body: body ) unless test_mode
  66. return unless DeepBlueDocs::Application.config.embargo_about_to_expire_email_rds
  67. email = ::Deepblue::EmailHelper.notification_email
  68. ::Deepblue::EmailHelper.log( class_name: self.class.name,
  69. current_user: nil,
  70. event: "Embargo expiration notification",
  71. event_note: event_note,
  72. id: id,
  73. to: email,
  74. from: email,
  75. subject: subject,
  76. body: body )
  77. ::Deepblue::EmailHelper.send_email( to: email, from: email, subject: subject, body: body ) unless test_mode
  78. end
  79. 1 def days_to_embargo_release_date( now: DateTime.now, embargo_release_date: )
  80. embargo_release_date = DateTime.parse "#{embargo_release_date} #{Time.zone}" if embargo_release_date.is_a? String
  81. ((embargo_release_date - @start_of_day).to_f + 0.5).to_i
  82. end
  83. # Update the visibility of the work to match the correct state of the embargo, then clear the embargo date, etc.
  84. # Saves the embargo and the work
  85. 1 def deactivate_embargo( curation_concern:,
  86. copy_visibility_to_files:,
  87. current_user:,
  88. email_owner: true,
  89. test_mode: false,
  90. verbose: false )
  91. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  92. ::Deepblue::LoggingHelper.called_from,
  93. ::Deepblue::LoggingHelper.obj_class( "curation_concern", curation_concern ),
  94. "copy_visibility_to_files=#{copy_visibility_to_files}",
  95. "email_owner=#{email_owner}",
  96. "test_mode=#{test_mode}",
  97. "verbose=#{verbose}",
  98. "" ]
  99. # also probably want to lock the model
  100. current_user = Deepblue::ProvenanceHelper.system_as_current_user unless current_user.present?
  101. embargo_visibility = curation_concern.visibility
  102. if curation_concern.is_a? FileSet
  103. ::Deepblue::LoggingHelper.debug "deactivate_embargo for file_set: curation concern id: #{curation_concern.id}" if verbose
  104. curation_concern.visibility = visibility_on_embargo_deactivation( curation_concern: curation_concern )
  105. curation_concern.provenance_unembargo( current_user: Deepblue::ProvenanceHelper.system_as_current_user,
  106. embargo_visibility: embargo_visibility,
  107. embargo_visibility_after: curation_concern.visibility )
  108. curation_concern.save! unless test_mode
  109. else
  110. curation_concern.embargo_visibility! unless test_mode # If the embargo has lapsed, update the current visibility.
  111. curation_concern.deactivate_embargo!( current_user: Deepblue::ProvenanceHelper.system_as_current_user ) unless test_mode
  112. curation_concern.embargo.save! unless test_mode
  113. rv = false
  114. rv = curation_concern.save! unless test_mode
  115. curation_concern.copy_visibility_to_files if copy_visibility_to_files && !test_mode
  116. deactivate_embargo_email( curation_concern: curation_concern, test_mode: test_mode ) if email_owner
  117. rv
  118. end
  119. end
  120. 1 def deactivate_embargo_email( curation_concern:, test_mode:, verbose: false )
  121. id = curation_concern.id
  122. title = curation_concern.title.join
  123. subject = ::Deepblue::EmailHelper.t( "hyrax.email.deactivate_embargo.subject", title: title )
  124. url = ::Deepblue::EmailHelper.curation_concern_url( curation_concern: curation_concern )
  125. body = []
  126. body << ::Deepblue::EmailHelper.t( "hyrax.email.deactivate_embargo.for",
  127. title: title,
  128. id: id,
  129. visibility: curation_concern.visibility )
  130. body << ::Deepblue::EmailHelper.t( "hyrax.email.deactivate_embargo.visit", url: url )
  131. body = body.join( '' )
  132. event_note = ''
  133. event_note = "test_mode" if test_mode
  134. email = curation_concern.authoremail
  135. ::Deepblue::LoggingHelper.debug "deactivate_embargo_email: curation concern id: #{id} email: #{email}" if verbose
  136. ::Deepblue::EmailHelper.log( class_name: self.class.name,
  137. current_user: nil,
  138. event: "Deactivate embargo",
  139. event_note: event_note,
  140. id: id,
  141. to: email,
  142. from: email,
  143. subject: subject,
  144. body: body )
  145. ::Deepblue::EmailHelper.send_email( to: email, from: email, subject: subject, body: body ) unless test_mode
  146. return unless DeepBlueDocs::Application.config.embargo_deactivate_email_rds
  147. email = ::Deepblue::EmailHelper.notification_email
  148. ::Deepblue::LoggingHelper.debug "deactivate_embargo_email: curation concern id: #{id} email: #{email}" if verbose
  149. ::Deepblue::EmailHelper.log( class_name: self.class.name,
  150. current_user: nil,
  151. event: "Deactivate embargo",
  152. event_note: event_note,
  153. id: id,
  154. to: email,
  155. from: email,
  156. subject: subject,
  157. body: body )
  158. ::Deepblue::EmailHelper.send_email( to: email, from: email, subject: subject, body: body ) unless test_mode
  159. end
  160. 1 def embargo_added( curation_concern:, update_attr_key_values: )
  161. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  162. ::Deepblue::LoggingHelper.called_from,
  163. ::Deepblue::LoggingHelper.obj_class( "curation_concern", curation_concern ),
  164. "curation_concern.id=#{curation_concern.id}",
  165. "update_attr_key_values=#{update_attr_key_values}",
  166. "" ]
  167. false
  168. end
  169. 1 def have_assets_under_embargo?( current_user_key )
  170. embargoes = my_assets_under_embargo( current_user_key )
  171. return false if embargoes.blank?
  172. hide_files = DeepBlueDocs::Application.config.embargo_manage_hide_files
  173. return true unless hide_files
  174. embargoes.each do |curation_concern|
  175. hrt = curation_concern.human_readable_type
  176. return true if hrt != 'File'
  177. end
  178. return false
  179. end
  180. 1 def my_assets_with_expired_embargoes( current_user_key )
  181. @my_assets_with_expired_embargoes ||= EmbargoService.my_assets_with_expired_embargoes( current_user_key )
  182. end
  183. 1 def my_assets_under_embargo( current_user_key )
  184. @my_assets_under_embargo ||= EmbargoService.my_assets_under_embargo( current_user_key )
  185. end
  186. 1 def my_assets_with_deactivated_embargoes( current_user_key )
  187. @my_assets_with_deactivated_embargoes ||= EmbargoService.my_assets_with_deactivated_embargoes( current_user_key )
  188. end
  189. 1 def warn_deactivate_embargo_email( curation_concern:, days: )
  190. # TODO
  191. end
  192. 1 def visibility_on_embargo_deactivation( curation_concern: )
  193. curation_concern.to_solr["visibility_after_embargo_ssim"]
  194. end
  195. end
  196. end

app/helpers/hyrax_helper.rb

45.83% lines covered

24 relevant lines. 11 lines covered and 13 lines missed.
    
  1. 1 module HyraxHelper
  2. 1 include ::BlacklightHelper
  3. 1 include Hyrax::BlacklightOverride
  4. 1 include Hyrax::HyraxHelperBehavior
  5. # override hyrax method
  6. # Which translations are available for the user to select
  7. # @return [Hash{String => String}] locale abbreviations as keys and flags as values
  8. 1 def available_translations
  9. {
  10. 3 'en' => 'English'
  11. }
  12. end
  13. # @param [Hash] options from blacklight invocation of helper_method
  14. # @see #index_field_link params
  15. # @return [String]
  16. 1 def human_readable_file_size(options)
  17. value = options[:value].first
  18. ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert( value, precision: 3 )
  19. end
  20. # def link_to_profile(login)
  21. # user = ::User.find_by_user_key(login)
  22. # return login if user.nil?
  23. #
  24. # text = if user.respond_to? :name
  25. # user.name
  26. # else
  27. # login
  28. # end
  29. #
  30. # href = profile_path(user)
  31. #
  32. # # TODO: ?? still needed ?? Fix the link to the user profiles when the sufia object isn't available.
  33. # link_to text, href
  34. # end
  35. 1 def self.nbsp_or_value( value )
  36. return "&nbsp;" if value.nil?
  37. return "&nbsp;" if value.to_s.empty?
  38. return value
  39. end
  40. # Overrides AbilityHelper.render_visibility_link to fix bug reported in
  41. # UMRDR issue 727: Link provided by render_visibility_link method had
  42. # path that displays a form to edit all attributes for a document. New
  43. # method simply renders the visibility_badge for the document.
  44. 1 def render_visibility_link(document)
  45. visibility_badge(document.visibility)
  46. end
  47. # A Blacklight index field helper_method
  48. # @param [Hash] options from blacklight helper_method invocation. Maps rights statement URIs to links with labels.
  49. # @return [ActiveSupport::SafeBuffer] rights statement links, html_safe
  50. 1 def rights_license_links(options)
  51. service = Hyrax::RightsLicenseService.new
  52. to_sentence(options[:value].map { |right| link_to service.label(right), right })
  53. end
  54. 1 def t_uri(key, scope: [])
  55. new_scope = scope.collect do |arg|
  56. if arg.is_a?(String)
  57. arg.tr('.', '_')
  58. else
  59. arg
  60. end
  61. end
  62. I18n.t(key, scope: new_scope)
  63. end
  64. end

app/helpers/job_helper.rb

33.33% lines covered

6 relevant lines. 2 lines covered and 4 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module JobHelper
  3. 1 def job_options_value(options, key:, default_value: nil, verbose: false )
  4. return default_value if options.blank?
  5. return default_value unless options.key? key
  6. # if [true, false].include? default_value
  7. # return options[key].to_bool
  8. # end
  9. ::Deepblue::LoggingHelper.debug "set key #{key} to #{options[key]}" if verbose
  10. return options[key]
  11. end
  12. end

app/helpers/msg_helper.rb

58.82% lines covered

17 relevant lines. 10 lines covered and 7 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module MsgHelper
  3. 1 extend ActionView::Helpers::TranslationHelper
  4. 1 FIELD_SEP = '; '
  5. 1 def self.creator( curation_concern, field_sep: FIELD_SEP )
  6. curation_concern.creator.join( field_sep )
  7. end
  8. 1 def self.description( curation_concern, field_sep: FIELD_SEP )
  9. curation_concern.description.join( field_sep )
  10. end
  11. 1 def self.globus_link( curation_concern )
  12. ::GlobusJob.external_url curation_concern.id
  13. end
  14. 1 def self.publisher( curation_concern, field_sep: FIELD_SEP )
  15. curation_concern.publisher.join( field_sep )
  16. end
  17. 1 def self.subject_discipline( curation_concern, field_sep: FIELD_SEP )
  18. curation_concern.subject_discipline.join( field_sep )
  19. end
  20. 1 def self.title( curation_concern, field_sep: FIELD_SEP )
  21. curation_concern.title.join( field_sep )
  22. end
  23. 1 def self.work_location( curation_concern: nil )
  24. # Rails.application.routes.url_helpers.hyrax_data_set_url( id: curation_concern.id )
  25. # Rails.application.routes.url_helpers.url_for( only_path: false,
  26. # action: 'show',
  27. # host: "http://todo.com",
  28. # controller: 'concern/data_sets',
  29. # id: id )
  30. "work location for: #{curation_concern.class.name} #{curation_concern.id}"
  31. end
  32. end

app/indexers/data_set_indexer.rb

26.67% lines covered

15 relevant lines. 4 lines covered and 11 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class DataSetIndexer < Hyrax::WorkIndexer
  3. # This indexes the default metadata. You can remove it if you want to
  4. # provide your own metadata and indexing.
  5. 1 include Hyrax::IndexesBasicMetadata
  6. # Fetch remote labels for based_near. You can remove this if you don't want
  7. # this behavior
  8. 1 include Hyrax::IndexesLinkedMetadata
  9. # Uncomment this block if you want to add custom indexing behavior:
  10. # def generate_solr_document
  11. # super.tap do |solr_doc|
  12. # solr_doc['my_custom_field_ssim'] = object.my_custom_property
  13. # end
  14. # end
  15. 1 def generate_solr_document
  16. super.tap do |solr_doc|
  17. # ### same as
  18. # solr_doc[Solrizer.solr_name('member_ids', :symbol)] = object.member_ids
  19. # solr_doc[Solrizer.solr_name('member_of_collections', :symbol)] = object.member_of_collections.map(&:first_title)
  20. # solr_doc[Solrizer.solr_name('member_of_collection_ids', :symbol)] = object.member_of_collections.map(&:id)
  21. # ### this:
  22. # solr_doc['member_ids_ssim'] = object.member_ids
  23. # solr_doc['member_of_collections_ssim'] = object.member_of_collections.map(&:first_title)
  24. # solr_doc['member_of_collection_ids_ssim'] = object.member_of_collections.map(&:id)
  25. solr_doc[Solrizer.solr_name('creator_ordered', :stored_searchable)] = object.creator_ordered
  26. solr_doc[Solrizer.solr_name('doi', :symbol)] = object.doi
  27. value = Array( object.referenced_by ).join( " " )
  28. solr_doc[Solrizer.solr_name('referenced_by', :stored_searchable)] = value
  29. # solr_doc[Solrizer.solr_name('referenced_by', :stored_sortable)] = value
  30. # So that we can sort by title.
  31. value = Array( object.title ).join( " " )
  32. solr_doc[Solrizer.solr_name('title', :stored_searchable,)] = value
  33. solr_doc[Solrizer.solr_name('title', :stored_sortable)] = value
  34. solr_doc[Solrizer.solr_name('title_ordered', :stored_searchable)] = object.title_ordered
  35. solr_doc[Solrizer.solr_name('tombstone', :symbol)] = object.tombstone
  36. # solr_doc[Solrizer.solr_name('total_file_size', Hyrax::FileSetIndexer::STORED_LONG)] = object.total_file_size
  37. solr_doc[Solrizer.solr_name('total_file_size', Hyrax::FileSetIndexer::STORED_LONG)] = object.size_of_work
  38. # ### same as
  39. # admin_set_label = object.admin_set.to_s
  40. # solr_doc[Solrizer.solr_name('admin_set', :facetable)] = admin_set_label
  41. # solr_doc[Solrizer.solr_name('admin_set', :stored_searchable)] = admin_set_label
  42. # ### this:
  43. # admin_set_label = object.admin_set.to_s
  44. # solr_doc['admin_set_sim'] = admin_set_label
  45. # solr_doc['admin_set_tesim'] = admin_set_label
  46. end
  47. end
  48. end

app/indexers/dissertation_indexer.rb

100.0% lines covered

3 relevant lines. 3 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work Dissertation`
  3. 1 class DissertationIndexer < Hyrax::WorkIndexer
  4. # This indexes the default metadata. You can remove it if you want to
  5. # provide your own metadata and indexing.
  6. 1 include Hyrax::IndexesBasicMetadata
  7. # Fetch remote labels for based_near. You can remove this if you don't want
  8. # this behavior
  9. 1 include Hyrax::IndexesLinkedMetadata
  10. # Uncomment this block if you want to add custom indexing behavior:
  11. # def generate_solr_document
  12. # super.tap do |solr_doc|
  13. # solr_doc['my_custom_field_ssim'] = object.my_custom_property
  14. # end
  15. # end
  16. end

app/indexers/generic_work_indexer.rb

100.0% lines covered

3 relevant lines. 3 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work GenericWork`
  3. 1 class GenericWorkIndexer < Hyrax::WorkIndexer
  4. # This indexes the default metadata. You can remove it if you want to
  5. # provide your own metadata and indexing.
  6. 1 include Hyrax::IndexesBasicMetadata
  7. # Fetch remote labels for based_near. You can remove this if you don't want
  8. # this behavior
  9. 1 include Hyrax::IndexesLinkedMetadata
  10. # Uncomment this block if you want to add custom indexing behavior:
  11. # def generate_solr_document
  12. # super.tap do |solr_doc|
  13. # solr_doc['my_custom_field_ssim'] = object.my_custom_property
  14. # end
  15. # end
  16. end

app/indexers/hyrax/collection_with_basic_metadata_indexer.rb

66.67% lines covered

6 relevant lines. 4 lines covered and 2 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 class CollectionWithBasicMetadataIndexer < CollectionIndexer
  4. 1 include Hyrax::IndexesBasicMetadata
  5. 1 def generate_solr_document
  6. super.tap do |solr_doc|
  7. solr_doc[Solrizer.solr_name('creator_ordered', :stored_searchable)] = object.creator_ordered
  8. end
  9. end
  10. end
  11. end

app/indexers/hyrax/file_set_indexer.rb

21.43% lines covered

42 relevant lines. 9 lines covered and 33 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. # monkey
  4. 1 class FileSetIndexer < ActiveFedora::IndexingService
  5. 1 include Hyrax::IndexesThumbnails
  6. 1 include Hyrax::IndexesBasicMetadata
  7. 1 STORED_LONG = Solrizer::Descriptor.new(:long, :stored)
  8. 1 def generate_solr_document
  9. super.tap do |solr_doc|
  10. solr_doc['hasRelatedMediaFragment_ssim'] = object.representative_id
  11. solr_doc['hasRelatedImage_ssim'] = object.thumbnail_id
  12. # Label is the actual file name. It's not editable by the user.
  13. solr_doc['label_tesim'] = object.label
  14. solr_doc['label_ssi'] = object.label
  15. solr_doc['file_format_tesim'] = file_format
  16. solr_doc['file_format_sim'] = file_format
  17. # ::Deepblue::LoggingHelper.bold_debug "FileSetIndex.generate_solr_document #{object.class} #{object.file_size[0]}"
  18. solr_doc['file_size_lts'] = object.file_size[0]
  19. # ::Deepblue::LoggingHelper.bold_debug "FileSetIndex.generate_solr_document solr_doc['file_size_lts'] = #{solr_doc['file_size_lts']}"
  20. solr_doc['all_text_timv'] = object.extracted_text.content if object.extracted_text.present?
  21. solr_doc['height_is'] = Integer(object.height.first) if object.height.present?
  22. solr_doc['width_is'] = Integer(object.width.first) if object.width.present?
  23. solr_doc['visibility_ssi'] = object.visibility
  24. solr_doc['mime_type_ssi'] = object.mime_type
  25. # Index the Fedora-generated SHA1 digest to create a linkage between
  26. # files on disk (in fcrepo.binary-store-path) and objects in the repository.
  27. solr_doc['digest_ssim'] = digest_from_content
  28. solr_doc['page_count_tesim'] = object.page_count
  29. solr_doc['file_title_tesim'] = object.file_title
  30. solr_doc['duration_tesim'] = object.duration
  31. solr_doc['sample_rate_tesim'] = object.sample_rate
  32. solr_doc['original_checksum_tesim'] = object.original_checksum
  33. parent = object.parent
  34. if parent
  35. solr_doc['parented_bsi'] = true
  36. solr_doc['is_child_of_ssi'] = parent.id
  37. solr_doc['parent_path_tesi'] = Rails.application.routes.url_helpers.polymorphic_path(parent)
  38. else
  39. solr_doc['parented_bsi'] = false
  40. end
  41. end
  42. end
  43. 1 private
  44. 1 def digest_from_content
  45. return unless object.original_file
  46. object.original_file.digest.first.to_s
  47. end
  48. 1 def file_format
  49. if object.mime_type.present? && object.format_label.present?
  50. "#{object.mime_type.split('/').last} (#{object.format_label.join(', ')})"
  51. elsif object.mime_type.present?
  52. object.mime_type.split('/').last
  53. elsif object.format_label.present?
  54. object.format_label
  55. end
  56. end
  57. end
  58. end

app/jobs/about_to_expire_embargoes_job.rb

87.5% lines covered

24 relevant lines. 21 lines covered and 3 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require_relative '../services/deepblue/about_to_expire_embargoes_service'
  3. 1 class AboutToExpireEmbargoesJob < ::Hyrax::ApplicationJob
  4. 1 include JobHelper
  5. 1 queue_as :scheduler
  6. 1 def perform( *args )
  7. 2 ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  8. Deepblue::LoggingHelper.called_from,
  9. Deepblue::LoggingHelper.obj_class( 'class', self ),
  10. "args=#{args}",
  11. Deepblue::LoggingHelper.obj_class( 'args', args ),
  12. "" ]
  13. 2 ::Deepblue::SchedulerHelper.log( class_name: self.class.name, event: "about_to_expire_embargoes" )
  14. 2 options = {}
  15. 4 args.each { |key,value| options[key] = value }
  16. 2 ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  17. "options=#{options}",
  18. Deepblue::LoggingHelper.obj_class( 'options', options ),
  19. "" ]
  20. 2 verbose = job_options_value(options, key: 'verbose', default_value: false )
  21. 2 ::Deepblue::LoggingHelper.debug "verbose=#{verbose}" if verbose
  22. 2 email_owner = job_options_value(options, key: 'email_owner', default_value: true )
  23. 2 ::Deepblue::LoggingHelper.debug "email_owner=#{email_owner}" if verbose
  24. 2 expiration_lead_days = job_options_value(options, key: 'expiration_lead_days' )
  25. 2 ::Deepblue::LoggingHelper.debug "expiration_lead_days=#{expiration_lead_days}" if verbose
  26. 2 skip_file_sets = job_options_value(options, key: 'skip_file_sets', default_value: true )
  27. 2 ::Deepblue::LoggingHelper.debug "@skip_file_sets=#{skip_file_sets}" if verbose
  28. 2 test_mode = job_options_value(options, key: 'test_mode', default_value: false )
  29. 2 ::Deepblue::LoggingHelper.debug "test_mode=#{test_mode}" if verbose
  30. 2 ::Deepblue::AboutToExpireEmbargoesService.new( email_owner: email_owner,
  31. expiration_lead_days: expiration_lead_days,
  32. skip_file_sets: skip_file_sets,
  33. test_mode: test_mode,
  34. verbose: verbose ).run
  35. rescue Exception => e # rubocop:disable Lint/RescueException
  36. Rails.logger.error "#{e.class} #{e.message} at #{e.backtrace[0]}"
  37. Rails.logger.error e.backtrace.join("\n")
  38. raise e
  39. end
  40. end

app/jobs/globus_copy_job.rb

13.46% lines covered

104 relevant lines. 14 lines covered and 90 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class GlobusCopyJob < GlobusJob
  3. 1 queue_as :globus_copy
  4. # @param [String] concern_id
  5. # @param [String, "Globus: " ] log_prefix
  6. # @param [boolean, false] generate_error
  7. # @param [integer, 0 ] delay_per_file_seconds
  8. # @param [String, nil ] user_email
  9. 1 def perform( concern_id, log_prefix: "Globus: ", generate_error: false, delay_per_file_seconds: 0, user_email: nil )
  10. globus_job_perform( concern_id: concern_id, email: user_email, log_prefix: "#{log_prefix}globus_copy_job" ) do
  11. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} begin copy" unless @globus_job_quiet
  12. @target_download_dir = target_download_dir2 @globus_concern_id
  13. @target_prep_dir = target_prep_dir2( @globus_concern_id, prefix: nil, mkdir: true )
  14. @target_prep_dir_tmp = target_prep_tmp_dir2( @globus_concern_id, prefix: nil, mkdir: true )
  15. curation_concern = ActiveFedora::Base.find @globus_concern_id
  16. globus_email_rds( curation_concern: curation_concern, description: "copy job started for work #{curation_concern.id}" )
  17. metadata_file = curation_concern.metadata_report( dir: @target_prep_dir_tmp, filename_pre: 'w_' )
  18. move_destination = GlobusJob.target_file_name( @target_prep_dir, metadata_file.basename )
  19. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} mv #{metadata_file} to #{move_destination}" unless @globus_job_quiet
  20. FileUtils.move( metadata_file, move_destination )
  21. file_sets = curation_concern.file_sets
  22. do_copy_predicate = ->(target_file_name, _target_file) { globus_do_copy?( target_file_name ) }
  23. Deepblue::ExportFilesHelper.export_file_sets( target_dir: @target_prep_dir_tmp,
  24. file_sets: file_sets,
  25. log_prefix: @globus_log_prefix,
  26. do_export_predicate: do_copy_predicate ) do |target_file_name, target_file|
  27. sleep delay_per_file_seconds if delay_per_file_seconds.positive?
  28. move_destination = GlobusJob.target_file_name( @target_prep_dir, target_file_name )
  29. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} mv #{target_file} to #{move_destination}" unless @globus_job_quiet
  30. FileUtils.chmod( @@globus_copy_file_permissions, target_file )
  31. FileUtils.chown( nil, @@globus_copy_file_group, target_file ) unless @@globus_copy_file_group.blank?
  32. FileUtils.move( target_file, move_destination )
  33. if generate_error
  34. @globus_lock_file = nil
  35. raise StandardError, "generated error"
  36. end
  37. end
  38. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} mv #{@target_prep_dir} to #{@target_download_dir}" unless @globus_job_quiet
  39. FileUtils.move( @target_prep_dir, @target_download_dir )
  40. FileUtils.rmdir @target_prep_dir_tmp
  41. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} copy complete" unless @globus_job_quiet
  42. begin
  43. globus_copy_job_email_add( user_email )
  44. globus_copy_job_email_add( Deepblue::EmailHelper.notification_email )
  45. @email_lines = globus_copy_job_complete_lines( curation_concern )
  46. globus_copy_job_email_all
  47. globus_copy_job_email_clean
  48. rescue Exception => e # rubocop:disable Lint/RescueException
  49. # msg = "#{@globus_log_prefix} #{e.class}: #{e.message} at #{e.backtrace[0]}"
  50. msg = "#{@globus_log_prefix} #{e.class}: #{e.message} at #{e.backtrace.join("\n")}"
  51. Rails.logger.error msg
  52. end
  53. end
  54. end
  55. 1 def globus_copy_job_email_add( email = nil )
  56. email_file = globus_copy_job_email_file
  57. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} globus_copy_job_email_add #{email} to #{email_file}" unless @globus_job_quiet
  58. open( email_file, 'a' ) do |file|
  59. globus_file_lock( file ) do |out|
  60. out << if email.nil?
  61. ''
  62. else
  63. "#{email}\n"
  64. end
  65. end
  66. end
  67. end
  68. 1 protected
  69. 1 @email_lines = []
  70. 1 def globus_copy_job_complete_lines( curation_concern )
  71. lines = []
  72. lines << "Globus download is now available."
  73. lines << "Work: #{MsgHelper.title(curation_concern)}"
  74. lines << "At: #{MsgHelper.work_location(curation_concern: curation_concern)}"
  75. lines << "By: #{MsgHelper.creator(curation_concern)}"
  76. lines << "Deposited by: #{curation_concern.depositor}"
  77. lines << "Globus link: #{MsgHelper.globus_link(curation_concern)}"
  78. return lines
  79. rescue Exception => e # rubocop:disable Lint/RescueException
  80. # msg = "#{@globus_log_prefix} #{e.class}: #{e.message} at #{e.backtrace[0]}"
  81. msg = "#{@globus_log_prefix} #{e.class}: #{e.message} at #{e.backtrace.join("\n")}"
  82. Rails.logger.error msg
  83. end
  84. 1 def globus_copy_job_email_user( email: nil, lines: [] )
  85. return if email.blank?
  86. return if lines.blank?
  87. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} globus_copy_job_email_user: work id: #{@globus_concern_id} email: #{email}" unless @globus_job_quiet
  88. body = lines.join( "\n" )
  89. to = email
  90. from = email
  91. subject = 'DBD: Globus Work Files Available'
  92. Deepblue::EmailHelper.log( class_name: 'GlobusCopyJob',
  93. current_user: nil,
  94. event: Deepblue::AbstractEventBehavior::EVENT_GLOBUS,
  95. event_note: 'files available',
  96. id: @globus_concern_id,
  97. to: to,
  98. from: from,
  99. subject: subject,
  100. body: lines )
  101. Deepblue::EmailHelper.send_email( to: to, from: from, subject: subject, body: body )
  102. end
  103. 1 def globus_copy_job_email_all( emails: nil, lines: [] )
  104. emails = globus_copy_job_emails if emails.blank?
  105. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} globus_copy_job_email_all emails=#{emails}" unless @globus_job_quiet
  106. return if emails.count.zero?
  107. lines = @email_lines if lines.blank?
  108. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} globus_copy_job_email_all lines=#{lines}" unless @globus_job_quiet
  109. emails.each { |email| globus_copy_job_email_user( email: email, lines: lines ) }
  110. rescue Exception => e # rubocop:disable Lint/RescueException
  111. # msg = "#{@globus_log_prefix} #{e.class}: #{e.message} at #{e.backtrace[0]}"
  112. msg = "#{@globus_log_prefix} #{e.class}: #{e.message} at #{e.backtrace.join("\n")}"
  113. Rails.logger.error msg
  114. end
  115. 1 def globus_copy_job_emails
  116. email_addresses = {}
  117. email_file = globus_copy_job_email_file
  118. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} globus_copy_job_emails email_file=#{email_file}" unless @globus_job_quiet
  119. if File.exist? email_file
  120. # read the file, one email address per line
  121. open( email_file, 'r' ) do |file|
  122. globus_file_lock( file, mode: File::LOCK_SH ) do |fin|
  123. until fin.eof?
  124. line = fin.readline
  125. line = line.chomp!
  126. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} globus_copy_job_emails line=#{line}" unless @globus_job_quiet
  127. email_addresses[line] = true unless line.empty?
  128. end
  129. end
  130. end
  131. end
  132. return email_addresses.keys
  133. end
  134. 1 def globus_do_copy?( target_file_name )
  135. prep_file_name = GlobusJob.target_file_name( @target_prep_dir, target_file_name )
  136. do_copy = true
  137. if File.exist? prep_file_name
  138. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} skipping copy because #{prep_file_name} already exists" unless @globus_job_quiet
  139. do_copy = false
  140. end
  141. do_copy
  142. end
  143. 1 def globus_job_complete?
  144. globus_copy_job_complete? @globus_concern_id
  145. end
  146. 1 def globus_job_complete_file
  147. globus_ready_file
  148. end
  149. 1 def globus_job_perform_in_progress( email: nil )
  150. globus_copy_job_email_add( email )
  151. super.globus_job_perform_in_progress( email: email )
  152. end
  153. end

app/jobs/globus_job.rb

54.17% lines covered

216 relevant lines. 117 lines covered and 99 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class GlobusJob < ::Hyrax::ApplicationJob
  3. 1 @@globus_era_timestamp = DeepBlueDocs::Application.config.globus_era_timestamp
  4. 1 @@globus_era_token = DeepBlueDocs::Application.config.globus_era_token.freeze
  5. 1 @@globus_enabled = DeepBlueDocs::Application.config.globus_enabled.freeze
  6. 1 @@globus_base_file_name = DeepBlueDocs::Application.config.base_file_name.freeze
  7. 1 @@globus_base_url = DeepBlueDocs::Application.config.globus_base_url.freeze
  8. 1 @@globus_download_dir = DeepBlueDocs::Application.config.globus_download_dir.freeze
  9. 1 @@globus_prep_dir = DeepBlueDocs::Application.config.globus_prep_dir.freeze
  10. 1 @@globus_copy_file_group = DeepBlueDocs::Application.config.globus_copy_file_group.freeze
  11. 1 @@globus_copy_file_permissions = DeepBlueDocs::Application.config.globus_copy_file_permissions.freeze
  12. 1 def self.files_available?( concern_id )
  13. copy_complete? concern_id
  14. end
  15. 1 def self.copy_complete?( id )
  16. dir = @@globus_download_dir
  17. dir = dir.join files_target_file_name( id )
  18. Dir.exist? dir
  19. end
  20. 1 def self.clean_dir( dir_path, delete_dir: false )
  21. return unless Dir.exist? dir_path
  22. Dir.foreach( dir_path ) do |f|
  23. next if [ '.', '..' ].include? f
  24. clean_file File.join( dir_path, f )
  25. end
  26. return unless delete_dir
  27. Dir.delete dir_path
  28. end
  29. 1 def self.clean_file( file_path )
  30. File.delete file_path if File.exist? file_path
  31. end
  32. 1 def self.error_file( id )
  33. 1 target_file_name_env( @@globus_prep_dir, 'error', target_base_name( id ) )
  34. end
  35. 1 def self.error_file_contents( id )
  36. contents = nil
  37. return contents unless error_file_exists? id
  38. file = error_file id
  39. open( file, 'r' ) { |f| contents = f.readlines }
  40. return contents
  41. end
  42. 1 def self.error_file_exists?( id, write_error_to_log: false, log_prefix: '', quiet: true )
  43. 1 error_file = error_file( id )
  44. 1 error_file_exists = false
  45. 1 if File.exist? error_file
  46. if write_error_to_log
  47. msg = nil
  48. open( error_file, 'r' ) { |f| msg = f.read; msg.chomp! } # rubocop:disable Style/Semicolon
  49. Deepblue::LoggingHelper.debug "#{log_prefix} error file contains: #{msg}" unless quiet
  50. end
  51. error_file_exists = true
  52. end
  53. 1 error_file_exists
  54. end
  55. 1 def self.external_url( id )
  56. "#{@@globus_base_url}#{files_target_file_name(id)}%2F"
  57. end
  58. 1 def self.files_target_file_name( id = '' )
  59. "#{@@globus_base_file_name}#{id}"
  60. end
  61. 1 def self.files_prepping?( id )
  62. rv = !copy_complete?( id ) && locked?( id )
  63. rv
  64. end
  65. 1 def self.lock( concern_id, log_prefix )
  66. 1 lock_token = era_token
  67. 1 lock_file = lock_file concern_id
  68. 1 Deepblue::LoggingHelper.debug "#{log_prefix} writing lock token #{lock_token} to #{lock_file}" unless @globus_job_quiet
  69. 2 open( lock_file, 'w' ) { |f| f << lock_token << "\n" }
  70. 1 File.exist? lock_file
  71. end
  72. 1 def self.lock_file( id = '' )
  73. 3 target_file_name_env( @@globus_prep_dir, 'lock', target_base_name( id ) )
  74. end
  75. 1 def self.locked?( concern_id, log_prefix: '', quiet: true )
  76. 1 return false if error_file_exists?( concern_id, write_error_to_log: true, log_prefix: log_prefix, quiet: quiet )
  77. 1 lock_file = lock_file concern_id
  78. 1 return false unless File.exist? lock_file
  79. current_token = era_token
  80. lock_token = read_token lock_file
  81. rv = ( current_token == lock_token )
  82. Deepblue::LoggingHelper.debug "#{log_prefix} testing token from #{lock_file}: current_token: #{current_token} == lock_token: #{lock_token}: #{rv}" unless @quiet
  83. rv
  84. end
  85. 1 def self.read_token( token_file )
  86. token = nil
  87. open( token_file, 'r' ) { |f| token = f.read.chomp! }
  88. return token
  89. end
  90. 1 def self.server_prefix( str: '' )
  91. 16 "#{Rails.env}#{str}"
  92. end
  93. 1 def self.target_base_name( id = '', prefix: '', postfix: '' )
  94. 14 prefix = server_prefix( str: '_' ) if prefix.nil?
  95. 14 "#{prefix}#{@@globus_base_file_name}#{id}#{postfix}"
  96. end
  97. 1 def self.target_file_name_env( dir, file_type, base_name )
  98. 15 target_file_name( dir, ".#{server_prefix}.#{file_type}.#{base_name}" )
  99. end
  100. 1 def self.target_file_name( dir, filename, ext = '' )
  101. 16 return Pathname.new( filename + ext ) if dir.nil?
  102. 13 dir.join( filename + ext )
  103. end
  104. 1 def self.target_download_dir( concern_id )
  105. target_dir_name( @@globus_download_dir, target_base_name(concern_id ) )
  106. end
  107. 1 def self.target_dir_name( dir, subdir, mkdir: false )
  108. target_dir = dir.join subdir
  109. if mkdir
  110. Dir.mkdir(target_dir ) unless Dir.exist? target_dir
  111. end
  112. target_dir
  113. end
  114. 1 def self.target_prep_dir( concern_id, prefix: '', postfix: '', mkdir: false )
  115. prefix = server_prefix( str: '_' ) if prefix.nil?
  116. subdir = target_base_name( concern_id, prefix: prefix, postfix: postfix )
  117. target_dir_name( @@globus_prep_dir, subdir, mkdir: mkdir )
  118. end
  119. 1 def self.target_prep_tmp_dir( concern_id, prefix: '', postfix: '', mkdir: false )
  120. prefix = server_prefix( str: '_' ) if prefix.nil?
  121. dir = target_prep_dir( concern_id, prefix: prefix, postfix: "#{postfix}_tmp" )
  122. if mkdir
  123. Dir.mkdir(dir ) unless Dir.exist? dir
  124. end
  125. dir
  126. end
  127. 1 def self.era_token
  128. # read_token @@globus_era_file
  129. # read_token @@globus_era.era_file
  130. 2 @@globus_era_token
  131. end
  132. 1 def self.era_token_time
  133. timestamp = era_token
  134. Time.parse( timestamp )
  135. end
  136. # @param [String] concern_id
  137. # @param [String, "Globus: "] log_prefix
  138. 1 def perform( concern_id, log_prefix: "Globus: " )
  139. @globus_concern_id = concern_id
  140. @globus_log_prefix = log_prefix
  141. @globus_lock_file = GlobusJob.lock_file concern_id
  142. end
  143. 1 protected
  144. 1 def globus_acquire_lock?
  145. 1 return false if globus_locked?
  146. 1 globus_lock
  147. end
  148. 1 def globus_copy_job_complete?( concern_id )
  149. Dir.exist? target_download_dir2 concern_id
  150. end
  151. 1 def globus_copy_job_email_clean
  152. email_file = globus_copy_job_email_file
  153. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} globus_copy_job_email_reset exists? #{email_file}" unless @globus_job_quiet
  154. return unless File.exist? email_file
  155. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} globus_copy_job_email_reset delete #{email_file}" unless @globus_job_quiet
  156. File.delete email_file
  157. end
  158. 1 def globus_copy_job_email_file
  159. rv = GlobusJob.target_file_name_env( @@globus_prep_dir,
  160. 'copy_job_emails',
  161. GlobusJob.target_base_name( @globus_concern_id ) )
  162. return rv
  163. end
  164. 1 def globus_email_rds( curation_concern: nil, description: '' )
  165. curation_concern = ActiveFedora::Base.find @globus_concern_id if curation_concern.nil?
  166. return unless curation_concern.respond_to? :email_rds_globus
  167. curation_concern.email_rds_globus( current_user: nil, event_note: description )
  168. end
  169. 1 def globus_error( msg )
  170. file = globus_error_file
  171. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} writing error message to #{file}" unless @globus_job_quiet
  172. open( file, 'w' ) { |f| f << msg << "\n" }
  173. file
  174. end
  175. 1 def globus_error_file
  176. 2 GlobusJob.target_file_name_env( @@globus_prep_dir, 'error', GlobusJob.target_base_name( @globus_concern_id ) )
  177. end
  178. 1 def globus_error_file_exists?( write_error_to_log: false )
  179. GlobusJob.error_file_exists?( @globus_concern_id,
  180. write_error_to_log: write_error_to_log,
  181. log_prefix: @globus_log_prefix,
  182. quiet: @globus_job_quiet )
  183. end
  184. 1 def globus_error_reset
  185. 2 file = globus_error_file
  186. 2 File.delete file if File.exist? file
  187. 2 true
  188. end
  189. 1 def globus_file_lock( file, mode: File::LOCK_EX )
  190. success = true
  191. if File.exist? file
  192. success = file.flock( mode )
  193. if success
  194. begin
  195. yield file
  196. ensure
  197. file.flock( File::LOCK_UN )
  198. end
  199. end
  200. else
  201. yield file
  202. end
  203. return success
  204. end
  205. 1 def globus_job_perform( concern_id: '', email: nil, log_prefix: 'Globus: ', quiet: false ) # , &globus_block )
  206. 1 @globus_concern_id = concern_id
  207. 1 @globus_log_prefix = log_prefix
  208. 1 @globus_lock_file = nil
  209. 1 @globus_job_quiet = quiet
  210. 1 return unless @@globus_enabled
  211. begin
  212. 1 if globus_job_complete?
  213. globus_job_perform_already_complete( email: email )
  214. return
  215. end
  216. 1 @globus_lock_file = GlobusJob.lock_file @globus_concern_id
  217. 1 Deepblue::LoggingHelper.debug "#{@globus_log_prefix} lock file #{@globus_lock_file}" unless @globus_job_quiet
  218. rescue Exception => e # rubocop:disable Lint/RescueException
  219. msg = "#{@globus_log_prefix} #{e.class}: #{e.message} at #{e.backtrace[0]}"
  220. # Rails.logger.error msg
  221. Rails.logger.error "#{@globus_log_prefix} #{e.class}: #{e.message} at #{e.backtrace.join("\n")}"
  222. globus_error msg
  223. return
  224. end
  225. 1 unless globus_acquire_lock?
  226. globus_job_perform_in_progress( email: email )
  227. return
  228. end
  229. begin
  230. 1 globus_error_reset
  231. 1 globus_job_perform_complete_reset
  232. # globus_block.call
  233. 1 yield if block_given?
  234. 1 @globus_lock_file = globus_unlock
  235. 1 globus_job_perform_complete
  236. rescue Exception => e # rubocop:disable Lint/RescueException
  237. msg = "#{@globus_log_prefix} #{e.class}: #{e.message} at #{e.backtrace[0]}"
  238. Rails.logger.error msg
  239. globus_error msg
  240. ensure
  241. 1 globus_unlock
  242. end
  243. end
  244. 1 def globus_job_perform_already_complete( email: nil )
  245. if email.nil?
  246. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} skipping already complete globus job" unless @globus_job_quiet
  247. else
  248. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} skipping already complete globus job, email=#{email}" unless @globus_job_quiet
  249. end
  250. end
  251. 1 def globus_job_perform_in_progress( email: nil )
  252. if email.nil?
  253. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} skipping in progress globus job" unless @globus_job_quiet
  254. else
  255. Deepblue::LoggingHelper.debug "#{@globus_log_prefix} skipping in progress globus job, email=#{email}" unless @globus_job_quiet
  256. end
  257. end
  258. 1 def globus_job_perform_complete
  259. 1 file = globus_job_complete_file
  260. 1 timestamp = Time.now.to_s
  261. 2 open( file, 'w' ) { |f| f << timestamp << "\n" }
  262. 1 globus_error_reset
  263. 1 Deepblue::LoggingHelper.debug "#{@globus_log_prefix} job complete at #{timestamp}" unless @globus_job_quiet
  264. 1 return file
  265. end
  266. 1 def globus_job_perform_complete_reset
  267. 1 file = globus_job_complete_file
  268. 1 File.delete file if File.exist? file
  269. 1 true
  270. end
  271. 1 def globus_lock
  272. 1 GlobusJob.lock( @globus_concern_id, @globus_log_prefix )
  273. end
  274. 1 def globus_lock_file( id = '' )
  275. GlobusJob.lock_file id
  276. end
  277. 1 def globus_locked?
  278. 1 GlobusJob.locked?( @globus_concern_id, log_prefix: @globus_log_prefix, quiet: @globus_job_quiet )
  279. end
  280. 1 def globus_ready_file
  281. GlobusJob.target_file_name_env( @@globus_prep_dir, 'ready', GlobusJob.target_base_name( @globus_concern_id ) )
  282. end
  283. 1 def globus_unlock
  284. 2 return nil if @globus_lock_file.nil?
  285. 1 return nil unless File.exist? @globus_lock_file
  286. 1 Deepblue::LoggingHelper.debug "#{@globus_log_prefix} unlock by deleting file #{@globus_lock_file}" unless @globus_job_quiet
  287. 1 File.delete @globus_lock_file
  288. nil
  289. end
  290. 1 def target_download_dir2( concern_id )
  291. GlobusJob.target_download_dir( concern_id )
  292. end
  293. 1 def target_dir_name2( dir, subdir, mkdir: false )
  294. GlobusJob.target_dir_name( dir, subdir, mkdir: mkdir )
  295. end
  296. 1 def target_prep_dir2( concern_id, prefix: '', postfix: '', mkdir: false )
  297. GlobusJob.target_prep_dir( concern_id, prefix: prefix, postfix: postfix, mkdir: mkdir )
  298. end
  299. 1 def target_prep_tmp_dir2( concern_id, prefix: '', postfix: '', mkdir: false )
  300. GlobusJob.target_prep_tmp_dir( concern_id, prefix: prefix, postfix: postfix, mkdir: mkdir )
  301. end
  302. end

app/jobs/globus_restart_all_job.rb

98.18% lines covered

55 relevant lines. 54 lines covered and 1 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class GlobusRestartAllJob < GlobusJob
  3. 1 queue_as :globus_restart_all
  4. # @param [String, "Globus: "] log_prefix
  5. 1 def perform( log_prefix: "Globus: ", quiet: false )
  6. 1 Deepblue::LoggingHelper.debug "#{log_prefix}globus_restart_all_job starting..." unless quiet
  7. 1 globus_job_perform( concern_id: "Restart_All", log_prefix: "#{log_prefix}globus_restart_all_job", quiet: quiet ) do
  8. 1 Deepblue::LoggingHelper.debug "#{@globus_log_prefix} begin restart all" unless @globus_job_quiet
  9. 1 concern_ids_to_restart = {}
  10. 1 base_name = GlobusJob.target_base_name ''
  11. 1 prefix = GlobusJob.target_file_name_env(nil, 'lock', base_name ).to_s
  12. 1 lock_file_re = Regexp.compile( '^' + prefix + '([0-9a-z-]+)' + '$' )
  13. # Deepblue::LoggingHelper.debug "#{@globus_log_prefix} lock_file_re=#{lock_file_re}" unless @globus_job_quiet
  14. 1 prefix = GlobusJob.target_file_name_env(nil, 'error', base_name ).to_s
  15. 1 error_file_re = Regexp.compile( '^' + prefix + '([0-9a-z-]+)' + '$' )
  16. 1 prefix = GlobusJob.target_file_name( nil, "#{GlobusJob.server_prefix(str: '_')}#{base_name}" ).to_s
  17. 1 prep_dir_re = Regexp.compile( '^' + prefix + '([0-9a-z-]+)' + '$' )
  18. # Deepblue::LoggingHelper.debug "#{@globus_log_prefix} prep_dir_re=#{prep_dir_re}" unless @globus_job_quiet
  19. 1 prep_tmp_dir_re = Regexp.compile( '^' + prefix + '([0-9a-z-]+)_tmp' + '$' )
  20. 1 starts_with_path = "#{@@globus_prep_dir}#{File::SEPARATOR}"
  21. 1 files = Dir.glob( "#{starts_with_path}*" )
  22. # Deepblue::LoggingHelper.debug "#{@globus_log_prefix} files.size=#{files.size}" unless @globus_job_quiet
  23. 1 files.each do |f|
  24. # Deepblue::LoggingHelper.debug "#{@globus_log_prefix} processing #{f}"
  25. 11 f = f.slice( (starts_with_path.length)..(f.length) ) if f.starts_with? starts_with_path
  26. # Deepblue::LoggingHelper.debug "#{@globus_log_prefix} processing #{f}" unless @globus_job_quiet
  27. 11 match = lock_file_re.match( f )
  28. 11 if match
  29. # Deepblue::LoggingHelper.debug "#{@globus_log_prefix} lock_file_re=#{lock_file_re} matched #{f}" unless @globus_job_quiet
  30. 2 concern_id = match[1]
  31. 2 concern_ids_to_restart.store( concern_id, true )
  32. 2 next
  33. end
  34. 9 match = error_file_re.match( f )
  35. 9 if match
  36. # Deepblue::LoggingHelper.debug "#{@globus_log_prefix} lock_file_re=#{error_file_re} matched #{f}" unless @globus_job_quiet
  37. 1 concern_id = match[1]
  38. 1 concern_ids_to_restart.store( concern_id, true )
  39. 1 next
  40. end
  41. 8 match = prep_dir_re.match( f )
  42. 8 if match
  43. # Deepblue::LoggingHelper.debug "#{@globus_log_prefix} prep_dir_re=#{prep_dir_re} matched #{f}" unless @globus_job_quiet
  44. 2 concern_id = match[1]
  45. 2 concern_ids_to_restart.store( concern_id, true )
  46. 2 next
  47. end
  48. 6 match = prep_tmp_dir_re.match( f )
  49. 6 next unless match
  50. # Deepblue::LoggingHelper.debug "#{@globus_log_prefix} lock_file_re=#{prep_tmp_dir_re} matched #{f}" unless @globus_job_quiet
  51. 2 concern_id = match[1]
  52. 2 concern_ids_to_restart.store( concern_id, true )
  53. end
  54. 1 concern_ids_to_restart.keys.each do |concern_id|
  55. # Deepblue::LoggingHelper.debug "#{@globus_log_prefix} restart copy job #{concern_id}" unless @globus_job_quiet
  56. 5 ::GlobusCopyJob.perform_later( concern_id )
  57. end
  58. 1 Deepblue::LoggingHelper.debug "#{@globus_log_prefix} restart all complete" unless @globus_job_quiet
  59. end
  60. end
  61. 1 protected
  62. 1 def globus_job_complete_file
  63. 7 GlobusJob.target_file_name_env( @@globus_prep_dir, 'restarted', GlobusJob.target_base_name( @globus_concern_id ) )
  64. end
  65. 1 def globus_job_complete?
  66. 4 file = globus_job_complete_file
  67. 4 Deepblue::LoggingHelper.debug "#{@globus_log_prefix} globus job complete file #{file}" unless @globus_job_quiet
  68. 4 return false unless File.exist? file
  69. 2 last_complete_time = last_complete_time file
  70. 2 token_time = ::GlobusJob.era_token_time
  71. 2 Deepblue::LoggingHelper.debug "#{@globus_log_prefix} token_time:#{token_time} <= last_complete_time:#{last_complete_time}" unless @globus_job_quiet
  72. 2 Deepblue::LoggingHelper.debug "#{@globus_log_prefix} token_time.class:#{token_time.class} <= last_complete_time.class:#{last_complete_time.class}" unless @globus_job_quiet
  73. 2 token_time <= last_complete_time
  74. end
  75. 1 def last_complete_time( file )
  76. File.birthtime file
  77. end
  78. end

app/jobs/hyrax/application_job.rb

100.0% lines covered

2 relevant lines. 2 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. # A common base class for all Hyrax jobs.
  4. # This allows downstream applications to manipulate all the hyrax jobs by
  5. # including modules on this class.
  6. 1 class ApplicationJob < ::ActiveJob::Base
  7. end
  8. end

app/mailers/application_mailer.rb

100.0% lines covered

3 relevant lines. 3 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class ApplicationMailer < ActionMailer::Base
  3. 1 default from: 'from@example.com'
  4. 1 layout 'mailer'
  5. end

app/mailers/deepblue_mailer.rb

100.0% lines covered

5 relevant lines. 5 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class DeepblueMailer < ApplicationMailer
  3. 1 default from: Deepblue::EmailHelper.notification_email
  4. 1 layout "mailer.html"
  5. 1 def send_an_email( to:, from:, subject:, body: )
  6. 1 mail( to: to, from: from, subject: subject, body: body )
  7. end
  8. end

app/models/ability.rb

93.33% lines covered

30 relevant lines. 28 lines covered and 2 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class Ability
  3. 1 include Hydra::Ability
  4. 1 include Hyrax::Ability
  5. # self.ability_logic += [:everyone_can_create_curation_concerns]
  6. 1 self.ability_logic += [:deepblue_abilities]
  7. 1 def deepblue_abilities
  8. 20 alias_action :display_provenance_log, to: :read
  9. 20 alias_action :globus_clean_download, to: :delete
  10. 20 alias_action :globus_download, to: :read
  11. 20 alias_action :globus_add_email, to: :read
  12. 20 alias_action :globus_download_add_email, to: :read
  13. 20 alias_action :globus_download_notify_me, to: :read
  14. 20 alias_action :tombstone, to: :delete
  15. 20 alias_action :zip_download, to: :read
  16. # alias_action :confirm, to: :read
  17. # alias_action :identifiers, to: :update
  18. end
  19. # Define any customized permissions here.
  20. 1 def custom_permissions
  21. # Limits deleting objects to a the admin user
  22. #
  23. # if current_user.admin?
  24. # can [:destroy], ActiveFedora::Base
  25. # end
  26. # Limits creating new objects to a specific group
  27. #
  28. # if user_groups.include? 'special_group'
  29. # can [:create], ActiveFedora::Base
  30. # end
  31. # restrict depositing permissions
  32. 20 if can_deposit?
  33. 3 can [:create], DataSet
  34. 3 can [:doi], DataSet
  35. 3 can [:create], FileSet
  36. else
  37. 17 cannot [:create, :edit, :update, :destroy], DataSet
  38. 17 cannot [:create, :edit, :update, :destroy], FileSet
  39. end
  40. 20 if admin?
  41. # can [:create, :show, :add_user, :remove_user, :index, :edit, :update, :destroy], Role # uncomment to expose Role management in UI
  42. end
  43. end
  44. 1 def can_deposit?
  45. 20 admin? || depositor?
  46. end
  47. 1 def admin?
  48. 298 current_user.admin? || super
  49. end
  50. 1 def depositor?
  51. 19 depositing_role = Sipity::Role.find_by(name: Hyrax::RoleRegistry::DEPOSITING)
  52. 19 return false unless depositing_role
  53. Hyrax::Workflow::PermissionQuery.scope_processing_agents_for(user: current_user).any? do |agent|
  54. agent.workflow_responsibilities.joins(:workflow_role)
  55. .where('sipity_workflow_roles.role_id' => depositing_role.id).any?
  56. end
  57. end
  58. end

app/models/application_record.rb

100.0% lines covered

2 relevant lines. 2 lines covered and 0 lines missed.
    
  1. 1 class ApplicationRecord < ActiveRecord::Base
  2. 1 self.abstract_class = true
  3. end

app/models/collection.rb

41.62% lines covered

197 relevant lines. 82 lines covered and 115 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class Collection < ActiveFedora::Base
  3. 1 include ::Hyrax::CollectionBehavior
  4. # You can replace these metadata if they're not suitable
  5. # include Hyrax::BasicMetadata
  6. 1 include Umrdr::UmrdrWorkBehavior
  7. 1 include Umrdr::UmrdrWorkMetadata
  8. # This must be included at the end, because it finalizes the metadata
  9. # schema (by adding accepts_nested_attributes)
  10. 1 include ::Deepblue::DefaultMetadata
  11. 1 include ::Deepblue::MetadataBehavior
  12. 1 include ::Deepblue::EmailBehavior
  13. 1 include ::Deepblue::ProvenanceBehavior
  14. 1 before_destroy :provenance_before_destroy_collection
  15. 1 self.indexer = Hyrax::CollectionWithBasicMetadataIndexer
  16. 1 def provenance_before_destroy_collection
  17. # workflow_destroy does this
  18. # provenance_destroy( current_user: '' ) # , event_note: 'provenance_before_destroy_collection' )
  19. end
  20. 1 def metadata_keys_all
  21. %i[
  22. child_collection_ids
  23. child_collection_count
  24. child_work_ids
  25. child_work_count
  26. collection_type
  27. creator
  28. curation_notes_admin
  29. curation_notes_user
  30. date_created
  31. date_modified
  32. date_updated
  33. description
  34. keyword
  35. language
  36. prior_identifier
  37. referenced_by
  38. subject_discipline
  39. title
  40. total_file_size
  41. visibility
  42. ]
  43. end
  44. 1 def metadata_keys_brief
  45. %i[
  46. creator
  47. title
  48. visibility
  49. ]
  50. end
  51. 1 def metadata_keys_report
  52. %i[
  53. child_collection_count
  54. child_work_count
  55. collection_type
  56. creator
  57. curation_notes_user
  58. description
  59. keyword
  60. language
  61. referenced_by
  62. subject_discipline
  63. title
  64. total_file_size
  65. ]
  66. end
  67. 1 def metadata_keys_update
  68. %i[
  69. creator
  70. title
  71. visibility
  72. ]
  73. end
  74. 1 def attributes_all_for_email
  75. metadata_keys_all
  76. end
  77. 1 def attributes_all_for_provenance
  78. metadata_keys_all
  79. end
  80. 1 def attributes_brief_for_email
  81. metadata_keys_brief
  82. end
  83. 1 def attributes_brief_for_provenance
  84. metadata_keys_brief
  85. end
  86. 1 def attributes_standard_for_email
  87. metadata_keys_brief
  88. end
  89. 1 def attributes_update_for_email
  90. metadata_keys_update
  91. end
  92. 1 def attributes_update_for_provenance
  93. metadata_keys_update
  94. end
  95. 1 def for_email_route
  96. for_event_route
  97. end
  98. 1 def for_event_route
  99. Rails.application.routes.url_helpers.hyrax_data_set_path( id: self.id ) # rubocop:disable Style/RedundantSelf
  100. end
  101. 1 def for_provenance_route
  102. for_event_route
  103. end
  104. 1 def child_collection_count
  105. ActiveFedora::Base.where("member_of_collection_ids_ssim:#{id} AND generic_type_sim:Collection").count
  106. end
  107. 1 def child_collection_ids
  108. ActiveFedora::Base.where("member_of_collection_ids_ssim:#{id} AND generic_type_sim:Collection").map { |w| w.id } # rubocop:disable Style/SymbolProc
  109. end
  110. 1 def child_work_count
  111. ActiveFedora::Base.where("member_of_collection_ids_ssim:#{id} AND generic_type_sim:Work").count
  112. end
  113. 1 def child_work_ids
  114. ActiveFedora::Base.where("member_of_collection_ids_ssim:#{id} AND generic_type_sim:Work").map { |w| w.id } # rubocop:disable Style/SymbolProc
  115. end
  116. 1 def total_file_size
  117. 21 bytes
  118. end
  119. 1 def total_file_size_human_readable
  120. value = total_file_size
  121. ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert( value, precision: 3 )
  122. end
  123. 1 def title_type
  124. human_readable_type
  125. end
  126. 1 def map_email_attributes_override!( event:, # rubocop:disable Lint/UnusedMethodArgument
  127. attribute:,
  128. ignore_blank_key_values:,
  129. email_key_values: )
  130. value = nil
  131. handled = case attribute.to_s
  132. when 'child_collection_count'
  133. value = child_work_count
  134. true
  135. when 'child_collection_ids'
  136. value = collection_ids
  137. when 'child_work_count'
  138. value = child_work_count
  139. true
  140. when 'child_work_ids'
  141. value = child_work_ids
  142. true
  143. when 'collection_type'
  144. value = collection_type.machine_id
  145. true
  146. when 'total_file_size'
  147. value = total_file_size
  148. true
  149. when 'total_file_size_human_readable'
  150. value = total_file_size_human_readable
  151. true
  152. when 'visibility'
  153. value = visibility
  154. true
  155. else
  156. false
  157. end
  158. return false unless handled
  159. if ignore_blank_key_values
  160. email_key_values[attribute] = value if value.present?
  161. else
  162. email_key_values[attribute] = value
  163. end
  164. return true
  165. end
  166. 1 def map_provenance_attributes_override!( event:, # rubocop:disable Lint/UnusedMethodArgument
  167. attribute:,
  168. ignore_blank_key_values:,
  169. prov_key_values: )
  170. value = nil
  171. handled = case attribute.to_s
  172. when 'child_collection_count'
  173. value = child_work_count
  174. true
  175. when 'child_collection_ids'
  176. value = collection_ids
  177. when 'child_work_count'
  178. value = child_work_count
  179. true
  180. when 'child_work_ids'
  181. value = child_work_ids
  182. true
  183. when 'collection_type'
  184. value = collection_type.machine_id
  185. true
  186. when 'total_file_size'
  187. value = total_file_size
  188. true
  189. when 'total_file_size_human_readable'
  190. value = total_file_size_human_readable
  191. true
  192. when 'visibility'
  193. value = visibility
  194. true
  195. else
  196. false
  197. end
  198. return false unless handled
  199. if ignore_blank_key_values
  200. prov_key_values[attribute] = value if value.present?
  201. else
  202. prov_key_values[attribute] = value
  203. end
  204. return true
  205. end
  206. 1 def metadata_hash_override( key:, ignore_blank_values:, key_values: )
  207. value = nil
  208. handled = case key.to_s
  209. when 'child_collection_count'
  210. value = child_work_count
  211. true
  212. when 'child_collection_ids'
  213. value = collection_ids
  214. when 'child_work_count'
  215. value = child_work_count
  216. true
  217. when 'child_work_ids'
  218. value = child_work_ids
  219. true
  220. when 'collection_type'
  221. value = collection_type.machine_id
  222. true
  223. when 'total_file_size'
  224. value = total_file_size
  225. true
  226. when 'total_file_size_human_readable'
  227. value = total_file_size_human_readable
  228. true
  229. when 'visibility'
  230. value = visibility
  231. true
  232. else
  233. false
  234. end
  235. return false unless handled
  236. if ignore_blank_values
  237. key_values[key] = value if value.present?
  238. else
  239. key_values[key] = value
  240. end
  241. return true
  242. end
  243. 1 def metadata_report_contained_objects
  244. member_objects
  245. end
  246. 1 def metadata_report_keys
  247. return IGNORE_BLANK_KEY_VALUES, metadata_keys_report
  248. end
  249. 1 def metadata_report_label_override( metadata_key:, metadata_value: ) # rubocop:disable Lint/UnusedMethodArgument
  250. case metadata_key.to_s
  251. when 'child_collection_count'
  252. 'Child Collection Count: '
  253. when 'child_collection_ids'
  254. 'Child Collection Identifiers: '
  255. when 'child_work_count'
  256. 'Child Work Count: '
  257. when 'child_work_ids'
  258. 'Child Work Identifiers: '
  259. when 'collection_type'
  260. 'Collection Type: '
  261. when 'total_file_size'
  262. 'Total File Size: '
  263. when 'total_file_size_human_readable'
  264. 'Total File Size: '
  265. end
  266. end
  267. 1 def metadata_report_title_pre
  268. 'Collection: '
  269. end
  270. # begin metadata
  271. # the list of creators is ordered
  272. 1 def creator
  273. 21 values = super
  274. 21 values = Deepblue::MetadataHelper.ordered( ordered_values: creator_ordered, values: values )
  275. 21 return values
  276. end
  277. 1 def creator=( values )
  278. self.creator_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: creator_ordered, values: values )
  279. super values
  280. end
  281. # the list of curation_notes_admin is ordered
  282. 1 def curation_notes_admin
  283. 21 values = super
  284. 21 values = Deepblue::MetadataHelper.ordered( ordered_values: curation_notes_admin_ordered, values: values )
  285. 21 return values
  286. end
  287. 1 def curation_notes_admin=( values )
  288. self.curation_notes_admin_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: curation_notes_admin_ordered, values: values )
  289. super values
  290. end
  291. # the list of curation_notes_user is ordered
  292. 1 def curation_notes_user
  293. 21 values = super
  294. 21 values = Deepblue::MetadataHelper.ordered( ordered_values: curation_notes_user_ordered, values: values )
  295. 21 return values
  296. end
  297. 1 def curation_notes_user=( values )
  298. self.curation_notes_user_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: curation_notes_user_ordered, values: values )
  299. super values
  300. end
  301. # the list of description is ordered
  302. 1 def description
  303. 21 values = super
  304. 21 values = Deepblue::MetadataHelper.ordered( ordered_values: description_ordered, values: values )
  305. 21 return values
  306. end
  307. 1 def description=( values )
  308. self.description_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: description_ordered, values: values )
  309. super values
  310. end
  311. #
  312. # handle the list of referenced_by as ordered
  313. #
  314. 1 def referenced_by
  315. 21 values = super
  316. 21 values = Deepblue::MetadataHelper.ordered( ordered_values: referenced_by_ordered, values: values )
  317. 21 return values
  318. end
  319. 1 def referenced_by=( values )
  320. self.referenced_by_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: referenced_by_ordered, values: values )
  321. super values
  322. end
  323. #
  324. # the list of keyword is ordered
  325. #
  326. 1 def keyword
  327. 21 values = super
  328. 21 values = Deepblue::MetadataHelper.ordered( ordered_values: keyword_ordered, values: values )
  329. 21 return values
  330. end
  331. 1 def keyword=( values )
  332. self.keyword_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: keyword_ordered, values: values )
  333. super values
  334. end
  335. #
  336. # handle the list of language as ordered
  337. #
  338. 1 def language
  339. 21 values = super
  340. 21 values = Deepblue::MetadataHelper.ordered( ordered_values: language_ordered, values: values )
  341. 21 return values
  342. end
  343. 1 def language=( values )
  344. self.language_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: language_ordered, values: values )
  345. super values
  346. end
  347. # the list of title is ordered
  348. 1 def title
  349. 28 values = super
  350. 28 values = Deepblue::MetadataHelper.ordered( ordered_values: title_ordered, values: values )
  351. 28 return values
  352. end
  353. 1 def title=( values )
  354. 7 self.title_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: title_ordered, values: values )
  355. 7 super values
  356. end
  357. # end metadata
  358. end

app/models/concerns/deepblue/abstract_event_behavior.rb

100.0% lines covered

44 relevant lines. 44 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 class AbstractEventError < RuntimeError
  4. end
  5. 1 module AbstractEventBehavior
  6. 1 EVENT_CHARACTERIZE = 'characterize'
  7. 1 EVENT_CHILD_ADD = 'child_add'
  8. 1 EVENT_CHILD_REMOVE = 'child_remove'
  9. 1 EVENT_CREATE = 'create'
  10. 1 EVENT_CREATE_DERIVATIVE = 'create_derivative'
  11. 1 EVENT_DESTROY = 'destroy'
  12. 1 EVENT_DOWNLOAD = 'download'
  13. 1 EVENT_EMBARGO = 'embargo'
  14. 1 EVENT_FIXITY_CHECK = 'fixity_check'
  15. 1 EVENT_GLOBUS = 'globus'
  16. 1 EVENT_INGEST = 'ingest'
  17. 1 EVENT_MIGRATE = 'migrate'
  18. 1 EVENT_MINT_DOI = 'mint_doi'
  19. 1 EVENT_PUBLISH = 'publish'
  20. 1 EVENT_TOMBSTONE = 'tombstone'
  21. 1 EVENT_UNEMBARGO = 'unembargo'
  22. 1 EVENT_UNPUBLISH = 'unpublish'
  23. 1 EVENT_UPDATE = 'update'
  24. 1 EVENT_UPDATE_AFTER = 'update_after'
  25. 1 EVENT_UPDATE_BEFORE = 'update_before'
  26. 1 EVENT_UPDATE_VERSION = 'update_version'
  27. 1 EVENT_UPLOAD = 'upload'
  28. 1 EVENT_VIRUS_SCAN = 'virus_scan'
  29. 1 EVENT_WORKFLOW = 'workflow'
  30. EVENTS =
  31. [
  32. 1 EVENT_CHARACTERIZE,
  33. EVENT_CHILD_ADD,
  34. EVENT_CHILD_REMOVE,
  35. EVENT_CREATE,
  36. EVENT_CREATE_DERIVATIVE,
  37. EVENT_DESTROY,
  38. EVENT_DOWNLOAD,
  39. EVENT_EMBARGO,
  40. EVENT_FIXITY_CHECK,
  41. EVENT_GLOBUS,
  42. EVENT_INGEST,
  43. EVENT_MIGRATE,
  44. EVENT_MINT_DOI,
  45. EVENT_PUBLISH,
  46. EVENT_TOMBSTONE,
  47. EVENT_UNEMBARGO,
  48. EVENT_UNPUBLISH,
  49. EVENT_UPDATE,
  50. EVENT_UPDATE_AFTER,
  51. EVENT_UPDATE_BEFORE,
  52. EVENT_UPDATE_VERSION,
  53. EVENT_UPLOAD,
  54. EVENT_VIRUS_SCAN,
  55. EVENT_WORKFLOW
  56. ].freeze
  57. 1 IGNORE_BLANK_KEY_VALUES = true
  58. 1 USE_BLANK_KEY_VALUES = false
  59. 1 def event_attributes_cache_exist?( event:, id:, behavior: nil )
  60. 2 key = event_attributes_cache_key( event: event, id: id, behavior: behavior )
  61. 2 rv = Rails.cache.exist?( key )
  62. 2 rv
  63. end
  64. 1 def event_attributes_cache_fetch( event:, id:, behavior: nil )
  65. 2 key = event_attributes_cache_key( event: event, id: id, behavior: behavior )
  66. 2 rv = Rails.cache.fetch( key )
  67. 2 rv
  68. end
  69. 1 def event_attributes_cache_key( event:, id:, behavior: nil )
  70. 10 return "#{id}.#{event}" if behavior.blank?
  71. 4 "#{id}.#{event}.#{behavior}"
  72. end
  73. 1 def event_attributes_cache_write( event:, id:, attributes: DateTime.now, behavior: nil )
  74. 2 key = event_attributes_cache_key( event: event, id: id, behavior: behavior )
  75. 2 Rails.cache.write( key, attributes )
  76. end
  77. end
  78. end

app/models/concerns/deepblue/default_metadata.rb

100.0% lines covered

298 relevant lines. 298 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 module DefaultMetadata
  4. 1 extend ActiveSupport::Concern
  5. # Usage notes and expectations can be found in the Metadata Application Profile:
  6. # https://docs.google.com/spreadsheets/d/1koKjV7bjn7v4r5a3gsowEimljHiAwbwuOgjHe7FEtuw/edit?usp=sharing
  7. 1 included do # rubocop:disable Metrics/BlockLength
  8. 4 after_initialize :set_default_visibility
  9. 4 def set_default_visibility
  10. 57 self.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC if new_record?
  11. end
  12. 4 property :additional_information, predicate: ::RDF::Vocab::DC.description do |index|
  13. 8 index.as :stored_searchable
  14. end
  15. # multiple: false, until "conference" is converted to a nested attribute so that the location, name, and section are all related/stored together
  16. 4 property :conference_location, predicate: ::RDF::URI.new("http://d-nb.info/standards/elementset/gnd#placeOfConferenceOrEvent"), multiple: false do |index|
  17. 8 index.as :stored_searchable
  18. end
  19. # multiple: false, until "conference" is converted to a nested attribute so that the location, name, and section are all related/stored together
  20. 4 property :conference_name, predicate: ::RDF::Vocab::BIBO.presentedAt, multiple: false do |index|
  21. 8 index.as :stored_searchable, :facetable
  22. end
  23. # multiple: false, until "conference" is converted to a nested attribute so that the location, name, and section are all related/stored together
  24. 4 property :conference_section, predicate: ::RDF::URI.new("https://w2id.org/scholarlydata/ontology/conference-ontology.owl#Track"), multiple: false do |index|
  25. 8 index.as :stored_searchable, :facetable
  26. end
  27. # accessor attribute used only to group the date fields and allow proper ordering in the forms
  28. 4 attr_accessor :dates_section
  29. 4 property :date_accepted, predicate: ::RDF::Vocab::DC.dateAccepted, multiple: false do |index|
  30. 8 index.as :stored_searchable, :facetable
  31. end
  32. 4 property :date_collected, predicate: ::RDF::Vocab::DWC.measurementDeterminedDate do |index|
  33. 8 index.as :stored_searchable, :facetable
  34. end
  35. 4 property :date_reviewed, predicate: ::RDF::URI.new("http://schema.org/lastReviewed") do |index|
  36. 8 index.as :stored_searchable
  37. end
  38. 4 property :date_valid, predicate: ::RDF::Vocab::DC.valid, multiple: false do |index|
  39. 8 index.as :stored_searchable, :facetable
  40. end
  41. 4 property :degree_field, predicate: ::RDF::URI.new("http://vivoweb.org/ontology/core#majorField") do |index|
  42. 8 index.as :stored_searchable, :facetable
  43. end
  44. # accessor value used by AddOtherFieldOptionActor to persist "Other" values provided by the user
  45. 4 attr_accessor :degree_field_other
  46. 4 property :degree_level, predicate: ::RDF::URI.new("http://purl.org/NET/UNTL/vocabularies/degree-information/#level"), multiple: false do |index|
  47. 8 index.as :stored_searchable, :facetable
  48. end
  49. # accessor value used by AddOtherFieldOptionActor to persist "Other" values provided by the user
  50. 4 attr_accessor :degree_level_other
  51. # 67 description.thesisdegreename
  52. 4 property :degree_name, predicate: ::RDF::URI.new("http://purl.org/ontology/bibo/ThesisDegree") do |index|
  53. 8 index.as :stored_searchable, :facetable
  54. end
  55. # accessor value used by AddOtherFieldOptionActor to persist "Other" values provided by the user
  56. 4 attr_accessor :degree_name_other
  57. 4 property :digitization_spec, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/conversionSpecifications") do |index|
  58. 8 index.as :stored_searchable
  59. end
  60. # property :doi, predicate: ::RDF::Vocab::Identifiers.doi, multiple: false do |index|
  61. # index.as :stored_searchable, :facetable
  62. # end
  63. 4 property :dspace_collection, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/dspaceCollection") do |index|
  64. 8 index.as :stored_searchable
  65. end
  66. 4 property :dspace_community, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/dspaceCommunity") do |index|
  67. 8 index.as :stored_searchable
  68. end
  69. 4 property :file_extent, predicate: ::RDF::Vocab::DC.extent do |index|
  70. 8 index.as :stored_searchable
  71. end
  72. 4 property :funding_body, predicate: ::RDF::Vocab::MARCRelators.fnd do |index|
  73. 8 index.as :stored_searchable, :facetable
  74. end
  75. 4 property :funding_statement, predicate: ::RDF::URI.new("http://datacite.org/schema/kernel-4/fundingReference") do |index|
  76. 8 index.as :stored_searchable, :facetable
  77. end
  78. 4 property :hydrologic_unit_code, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/hydrologicUnitCode") do |index|
  79. 8 index.as :stored_searchable, :facetable
  80. end
  81. 4 property :import_url, predicate: ::RDF::URI.new('http://scholarsphere.psu.edu/ns#importUrl'), multiple: false do |index|
  82. 8 index.as :stored_searchable
  83. end
  84. 4 property :in_series, predicate: ::RDF::URI.new("http://lsdis.cs.uga.edu/projects/semdis/opus#in_series") do |index|
  85. 8 index.as :stored_searchable
  86. end
  87. 4 property :keyword, predicate: ::RDF::Vocab::DC11.subject do |index|
  88. 8 index.as :stored_searchable
  89. end
  90. 4 property :label, predicate: ActiveFedora::RDF::Fcrepo::Model.downloadFilename, multiple: false do |index|
  91. 8 index.as :stored_searchable
  92. end
  93. 4 property :license, predicate: ::RDF::Vocab::DC.rights do |index|
  94. 8 index.as :stored_searchable, :facetable
  95. end
  96. # property :nested_geo, :predicate => ::RDF::URI("https://purl.org/geojson/vocab#Feature"), :class_name => NestedGeo
  97. # property :nested_related_items, predicate: ::RDF::Vocab::DC.relation, :class_name => NestedRelatedItems do |index|
  98. # index.as :stored_searchable
  99. # end
  100. # accessor value used by AddOtherFieldOptionActor to persist "Other" values provided by the user
  101. 4 attr_accessor :other_affiliation_other
  102. 4 property :prior_identifier, predicate: ActiveFedora::RDF::Fcrepo::Model.altIds, multiple: true do |index|
  103. 8 index.as :stored_searchable
  104. end
  105. 4 property :related_url, predicate: ::RDF::RDFS.seeAlso do |index|
  106. 8 index.as :stored_searchable
  107. end
  108. 4 property :relative_path, predicate: ::RDF::URI.new('http://scholarsphere.psu.edu/ns#relativePath'), multiple: false do |index|
  109. 8 index.as :stored_searchable
  110. end
  111. 4 property :replaces, predicate: ::RDF::Vocab::DC.replaces, multiple: false do |index|
  112. 8 index.as :stored_searchable
  113. end
  114. 4 property :resource_type, predicate: ::RDF::Vocab::DC.type do |index|
  115. 8 index.as :stored_searchable, :facetable
  116. end
  117. 4 property :rights_statement, predicate: ::RDF::Vocab::EDM.rights do |index|
  118. 8 index.as :stored_searchable, :facetable
  119. end
  120. 4 property :source, predicate: ::RDF::Vocab::DC.source do |index|
  121. 8 index.as :stored_searchable
  122. end
  123. # START These are ALL the metadata from Dspace
  124. # 1 contributor author
  125. 4 property :contributor_author, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/contributorAuthor") do |index|
  126. 8 index.as :stored_searchable
  127. end
  128. # 2 contributor advisor
  129. 4 property :contributor_advisor, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/contributorAdvisor") do |index|
  130. 8 index.as :stored_searchable
  131. end
  132. # 3 contributor - part of basic metadata
  133. 4 property :contributor, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/contributorMain") do |index|
  134. 8 index.as :stored_searchable
  135. end
  136. # 4 contributor editor
  137. 4 property :contributor_editor, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/contributorEditor") do |index|
  138. 8 index.as :stored_searchable
  139. end
  140. # 5 contributor illustrator
  141. 4 property :contributor_illustrator, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/contributorIllustrator") do |index|
  142. 8 index.as :stored_searchable
  143. end
  144. # 6 contributor
  145. 4 property :contributor, predicate: ::RDF::Vocab::DC11.contributor do |index|
  146. 4 index.as :stored_searchable
  147. end
  148. # 7 coverage spatial - part of basic metadata
  149. 4 property :based_near, predicate: ::RDF::Vocab::DC.spatial, class_name: Hyrax::ControlledVocabularies::Location do |index|
  150. 8 index.as :stored_searchable, :facetable
  151. end
  152. # 8 coverage temporal
  153. 4 property :coverage_temporal, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/coverageTemporal") do |index|
  154. 8 index.as :stored_searchable
  155. end
  156. # 9 creator null - part of basic
  157. 4 property :creator, predicate: ::RDF::Vocab::DC11.creator do |index|
  158. 8 index.as :stored_searchable, :facetable
  159. end
  160. # 10 date
  161. 4 property :date, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/date") do |index|
  162. 8 index.as :stored_searchable
  163. end
  164. # 11 date accessioned
  165. 4 property :date_accessioned, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/dateAccessioned") do |index|
  166. 8 index.as :stored_searchable
  167. end
  168. # 12 date available
  169. 4 property :date_available, predicate: ::RDF::Vocab::DC.available, multiple: false do |index|
  170. 8 index.as :stored_searchable, :facetable
  171. end
  172. # 13 date copyright
  173. 4 property :date_copyright, predicate: ::RDF::Vocab::DC.dateCopyrighted, multiple: false do |index|
  174. 8 index.as :stored_searchable, :facetable
  175. end
  176. # 14 date created - part of basic metadata
  177. 4 property :date_created, predicate: ::RDF::Vocab::DC.created, multiple: false do |index|
  178. 8 index.as :stored_searchable, :facetable
  179. end
  180. # 15 date issued
  181. 4 property :date_issued, predicate: ::RDF::Vocab::DC.issued, multiple: false do |index|
  182. 8 index.as :stored_searchable, :facetable
  183. end
  184. # 16 date submitted
  185. 4 property :date_submitted, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/dateSubmitted") do |index|
  186. 8 index.as :stored_searchable
  187. end
  188. # 17 identifier - part of basic metadata
  189. 4 property :identifier, predicate: ::RDF::Vocab::DC.identifier do |index|
  190. 8 index.as :stored_searchable
  191. end
  192. # 18 identifier citation - part of basic metadata
  193. 4 property :bibliographic_citation, predicate: ::RDF::Vocab::DC.bibliographicCitation
  194. # 19 identifier govdoc
  195. 4 property :identifier_govdoc, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/identifierGovdoc") do |index|
  196. 8 index.as :stored_searchable
  197. end
  198. # 20 identifier isbn
  199. 4 property :isbn, predicate: ::RDF::Vocab::Identifiers.isbn do |index|
  200. 8 index.as :stored_searchable
  201. end
  202. # 21 identifier issn
  203. 4 property :issn, predicate: ::RDF::Vocab::Identifiers.issn do |index|
  204. 8 index.as :stored_searchable
  205. end
  206. # 22 identifier sici
  207. 4 property :identifier_sici, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/identifierSici") do |index|
  208. 8 index.as :stored_searchable
  209. end
  210. # 23 identifier ismn
  211. 4 property :identifier_ismn, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/identifierIsmn") do |index|
  212. 8 index.as :stored_searchable
  213. end
  214. # 24 identifier other
  215. 4 property :identifier_other, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/identifierOther") do |index|
  216. 8 index.as :stored_searchable
  217. end
  218. # 25 identifier uri
  219. 4 property :identifier_uri, predicate: ::RDF::Vocab::Identifiers.uri do |index|
  220. 8 index.as :stored_searchable
  221. end
  222. # 26 description
  223. 4 property :desciption_none, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionNone") do |index|
  224. 8 index.as :stored_searchable
  225. end
  226. # 26 description null - part of basic metadata
  227. 4 property :description, predicate: ::RDF::Vocab::DC11.description do |index|
  228. 8 index.as :stored_searchable
  229. end
  230. # 27 description abstract
  231. 4 property :description_abstract, predicate: ::RDF::Vocab::DC.abstract do |index|
  232. 8 index.as :stored_searchable
  233. end
  234. # 28 description provenance
  235. 4 property :description_provenance, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionProvenance") do |index|
  236. 8 index.as :stored_searchable
  237. end
  238. # 29 description sponsorship
  239. 4 property :description_sponsorship, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionSponsorship") do |index|
  240. 8 index.as :stored_searchable
  241. end
  242. # 30 description statementofresponsibility
  243. 4 property :description_statementofresponsibility, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionStatementofresponsibility") do |index|
  244. 8 index.as :stored_searchable
  245. end
  246. # 31 description tableofcontents
  247. 4 property :tableofcontents, predicate: ::RDF::Vocab::DC.tableOfContents do |index|
  248. 8 index.as :stored_searchable
  249. end
  250. # 32 description uri
  251. 4 property :description_uri, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionUri") do |index|
  252. 8 index.as :stored_searchable
  253. end
  254. # 33 format
  255. 4 property :file_format, predicate: ::RDF::Vocab::DC.FileFormat do |index|
  256. 8 index.as :stored_searchable, :facetable
  257. end
  258. # 34 format extent
  259. 4 property :format_extent, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/formatExtent") do |index|
  260. 8 index.as :stored_searchable
  261. end
  262. # 35 format medium
  263. 4 property :format_medium, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/formatMedium") do |index|
  264. 8 index.as :stored_searchable
  265. end
  266. # 36 format mimetype
  267. 4 property :format_mimetype, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/formatMimetype") do |index|
  268. 8 index.as :stored_searchable
  269. end
  270. # 37 language - not needed
  271. 4 property :language_none, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/languageNone") do |index|
  272. 8 index.as :stored_searchable
  273. end
  274. # 38 language iso - part of basic metadata
  275. 4 property :language, predicate: ::RDF::Vocab::DC11.language do |index|
  276. 8 index.as :stored_searchable, :facetable
  277. end
  278. # 39 publisher - part of basic metadata
  279. 4 property :publisher, predicate: ::RDF::Vocab::DC11.publisher do |index|
  280. 8 index.as :stored_searchable
  281. end
  282. # 40 relation
  283. 4 property :relation_none, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/relationNone") do |index|
  284. 8 index.as :stored_searchable
  285. end
  286. # 41 relation isformatof
  287. 4 property :relation_isformatof, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/relationIsformatof") do |index|
  288. 8 index.as :stored_searchable
  289. end
  290. # 42 relation ispartof
  291. 4 property :part_of, predicate: ::RDF::Vocab::DC.isPartOf do |index|
  292. 8 index.as :stored_searchable
  293. end
  294. # 43 relation ispartofseries
  295. 4 property :relation_ispartofseries, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/relationIspartofseries") do |index|
  296. 8 index.as :stored_searchable
  297. end
  298. # 44 relation haspart
  299. 4 property :relation_haspart, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/relationHaspart") do |index|
  300. 8 index.as :stored_searchable
  301. end
  302. # 45 relation isversionof
  303. 4 property :relation_isversionof, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/relationIsversionof") do |index|
  304. 8 index.as :stored_searchable
  305. end
  306. # 46 relation hasversion
  307. 4 property :relation_hasversion, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/relationHasversion") do |index|
  308. 8 index.as :stored_searchable
  309. end
  310. # 47 relation isbasedon
  311. 4 property :relation_isbaseson, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/relationIsbasedon") do |index|
  312. 8 index.as :stored_searchable
  313. end
  314. # 48 relation isreferencedby
  315. 4 property :relation_isreferenceby, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/relationIsreferebcedby") do |index|
  316. 8 index.as :stored_searchable
  317. end
  318. # 49 relation requires
  319. 4 property :relation_require, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/relationRequires") do |index|
  320. 8 index.as :stored_searchable
  321. end
  322. # 50 relation replaces
  323. 4 property :relation_replaces, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/relationReplaces") do |index|
  324. 8 index.as :stored_searchable
  325. end
  326. # 51 relation isreplacedby
  327. 4 property :relation_isrplacedby, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/relationIsreplacedby") do |index|
  328. 8 index.as :stored_searchable
  329. end
  330. # 52 relation uri
  331. 4 property :relation_uri, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/relationUri") do |index|
  332. 8 index.as :stored_searchable
  333. end
  334. # 53 rights
  335. 4 property :rights_None, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/rightsNone") do |index|
  336. 8 index.as :stored_searchable
  337. end
  338. # 54 rights uri
  339. 4 property :rights_uri, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/rightsUri") do |index|
  340. 8 index.as :stored_searchable
  341. end
  342. # 55 source - part of basic metadata
  343. 4 property :source, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/sourceNone") do |index|
  344. 4 index.as :stored_searchable
  345. end
  346. # 56 source uri
  347. 4 property :source_uri, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/sourceUri") do |index|
  348. 8 index.as :stored_searchable
  349. end
  350. # 57 subject - part of basic metadata
  351. 4 property :subject, predicate: ::RDF::Vocab::DC.subject do |index|
  352. 8 index.as :stored_searchable, :facetable
  353. end
  354. # 58 subject classification
  355. 4 property :source_classification, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/sourceClassification") do |index|
  356. 8 index.as :stored_searchable
  357. end
  358. # 59 subject ddc
  359. 4 property :subject_ddc, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/subjectDdc") do |index|
  360. 8 index.as :stored_searchable
  361. end
  362. # 60 subject lcc
  363. 4 property :subject_lcc, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/subjectLcc") do |index|
  364. 8 index.as :stored_searchable
  365. end
  366. # 61 subject lcsh
  367. 4 property :subject_lcsh, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/subjectLcsh") do |index|
  368. 8 index.as :stored_searchable
  369. end
  370. # 62 subject mesh
  371. 4 property :subject_mesh, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/subjectMesh") do |index|
  372. 8 index.as :stored_searchable
  373. end
  374. # 63 subject other
  375. 4 property :subject_other, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/subjectOther") do |index|
  376. 8 index.as :stored_searchable
  377. end
  378. # 64 title - part of basic metadata
  379. 4 property :title, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/titleNone") do |index|
  380. 4 index.as :stored_searchable
  381. end
  382. # 65 title alternative
  383. 4 property :alt_title, predicate: ::RDF::Vocab::DC.alternative do |index|
  384. 8 index.as :stored_searchable
  385. end
  386. # 66 type
  387. 4 property :type_none, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/typeNone") do |index|
  388. 8 index.as :stored_searchable
  389. end
  390. 4 property :type_snre, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/typeSnre") do |index|
  391. 8 index.as :stored_searchable
  392. end
  393. # 67 description thesisdegreename
  394. 4 property :description_thesisdegreename, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionThesisdegreename") do |index|
  395. 8 index.as :stored_searchable
  396. end
  397. # 68 description thesisdegreediscipline
  398. 4 property :description_thesisdegreediscipline, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionThesisdegreediscipline") do |index|
  399. 8 index.as :stored_searchable
  400. end
  401. # 69 description thesisdegreegrantor
  402. 4 property :description_thesisdegreegrantor, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionThesisdegreegrantor") do |index|
  403. 8 index.as :stored_searchable
  404. end
  405. # 70 contributor committeemember
  406. 4 property :contributor_committeemember, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/contributorCommitteemember") do |index|
  407. 8 index.as :stored_searchable
  408. end
  409. # 71 rights robots
  410. 4 property :rights_robots, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/rightsRobots") do |index|
  411. 8 index.as :stored_searchable
  412. end
  413. # 72 subject hlbsecondlevel
  414. 4 property :subject_hlbsecondlevel, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/subjectHlbsecondlevel") do |index|
  415. 8 index.as :stored_searchable
  416. end
  417. # 73 subject hlbtoplevel
  418. 4 property :subject_hlbtoplevel, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/subjectHlbtoplevel") do |index|
  419. 8 index.as :stored_searchable
  420. end
  421. # 74 description peerreviewed
  422. 4 property :peerreviewed, predicate: ::RDF::URI("http://purl.org/ontology/bibo/peerReviewed"), multiple: false do |index|
  423. 8 index.as :stored_searchable, :facetable
  424. end
  425. # 75 contributor affiliationum
  426. 4 property :academic_affiliation, predicate: ::RDF::URI("http://vivoweb.org/ontology/core#AcademicDepartment") do |index|
  427. 8 index.as :stored_searchable, :facetable
  428. end
  429. # 76 contributor affiliationother
  430. 4 property :other_affiliation, predicate: ::RDF::URI("http://vivoweb.org/ontology/core#Department") do |index|
  431. 8 index.as :stored_searchable, :facetable
  432. end
  433. # 77 contributor affiliationumcampus
  434. 4 property :contributor_affiliationumcampus, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/contributorAffiliationumcampus") do |index|
  435. 8 index.as :stored_searchable
  436. end
  437. # 78 identifier uniqname
  438. 4 property :identifier_uniqname, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/identifierUniqname") do |index|
  439. 8 index.as :stored_searchable
  440. end
  441. # 79 identifier videostream
  442. 4 property :identifier_videostream, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/identifierVideostream") do |index|
  443. 8 index.as :stored_searchable
  444. end
  445. # 80 identifier pmid
  446. 4 property :identifier_pmid, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/identifierPmid") do |index|
  447. 8 index.as :stored_searchable
  448. end
  449. # 81 identifier oclc
  450. 4 property :identifier_oclc, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/identifierOclc") do |index|
  451. 8 index.as :stored_searchable
  452. end
  453. # 82 description withdrawalreason
  454. 4 property :embargo_reason, predicate: ::RDF::Vocab::DC.accessRights, multiple: false do |index|
  455. 8 index.as :stored_searchable
  456. end
  457. # 83 description bitstreamurl
  458. 4 property :description_bitstreamurl, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionBitstreamurl") do |index|
  459. 8 index.as :stored_searchable
  460. end
  461. # 84 identifier doi
  462. 4 property :identifier_doi, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/identifierDoi") do |index|
  463. 8 index.as :stored_searchable
  464. end
  465. # 85 identifier source
  466. 4 property :identifier_source, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/identifierSource") do |index|
  467. 8 index.as :stored_searchable
  468. end
  469. # 86 identifier citedreference
  470. 4 property :identifier_citedreference, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/identifierCitedreference") do |index|
  471. 8 index.as :stored_searchable
  472. end
  473. # 87 contributor authoremail
  474. 4 property :contributor_authoremail, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/contributorAuthoremail") do |index|
  475. 8 index.as :stored_searchable
  476. end
  477. # 88 requestcopy email
  478. 4 property :requestcopy_email, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/requestcopyEmail") do |index|
  479. 8 index.as :stored_searchable
  480. end
  481. # 89 requestcopy name
  482. 4 property :requestcopy_name, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/requestcopyName") do |index|
  483. 8 index.as :stored_searchable
  484. end
  485. # 90 identifier imageclass
  486. 4 property :identifier_imageclass, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/identifierImageclass") do |index|
  487. 8 index.as :stored_searchable
  488. end
  489. # 91 description mapping
  490. 4 property :description_mapping, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionMapping") do |index|
  491. 8 index.as :stored_searchable
  492. end
  493. # 92 language rfc3066
  494. # 93 description version
  495. 4 property :description_version, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionVersion") do |index|
  496. 8 index.as :stored_searchable
  497. end
  498. # 94 rights holder
  499. 4 property :rights_holder, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/rightsHolder") do |index|
  500. 8 index.as :stored_searchable
  501. end
  502. # 95 date updated
  503. 4 property :date_updated, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/dateUpdated") do |index|
  504. 8 index.as :stored_searchable
  505. end
  506. # 96 description md5checksum
  507. 4 property :description_md5checksum, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionMd5checksum") do |index|
  508. 8 index.as :stored_searchable
  509. end
  510. # 97 rights access
  511. 4 property :rights_access, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/rightsAccess") do |index|
  512. 8 index.as :stored_searchable
  513. end
  514. # 99 description hathi
  515. 4 property :description_hathi, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionHathi") do |index|
  516. 8 index.as :stored_searchable
  517. end
  518. # 100 description restriction
  519. 4 property :description_restriction, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionRestriction") do |index|
  520. 8 index.as :stored_searchable
  521. end
  522. # 101 identifier orcid
  523. 4 property :identifier_orcid, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/identifierOrcid") do |index|
  524. 8 index.as :stored_searchable
  525. end
  526. # 102 description filedescription
  527. 4 property :description_filedescription, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionFiledescription") do |index|
  528. 8 index.as :stored_searchable
  529. end
  530. # 103 date open
  531. 4 property :date_open, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/dateOpen") do |index|
  532. 8 index.as :stored_searchable
  533. end
  534. # 104 rights copyright
  535. 4 property :rights_copyright, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/rightsCopyright") do |index|
  536. 8 index.as :stored_searchable
  537. end
  538. # 105 provenance
  539. 4 property :provenance_none, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/provenanceNone") do |index|
  540. 8 index.as :stored_searchable
  541. end
  542. # 106 rights license
  543. 4 property :rights_license, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/rightsLicense"), multiple: false do |index|
  544. 8 index.as :stored_searchable
  545. end
  546. 4 property :rights_license_other, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/rightsLicenseOther"), multiple: false do |index|
  547. 6 index.as :stored_searchable
  548. end
  549. 4 property :geo_location_box, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/georss/box"), multiple: false do |index|
  550. 8 index.as :stored_searchable
  551. end
  552. 4 property :geo_location_place, predicate: ::RDF::Vocab::DC11.coverage, multiple: false do |index|
  553. 8 index.as :stored_searchable
  554. end
  555. 4 property :license_other, predicate: ::RDF::Vocab::DC.license, multiple: true do |index|
  556. 8 index.as :stored_searchable
  557. end
  558. # 166 identifier slug
  559. 4 property :identifier_slug, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/identifierSlug") do |index|
  560. 8 index.as :stored_searchable
  561. end
  562. # 167 description depositor - part of basic metadata :depositor
  563. # property :depositor, predicate: ::RDF::URI.new("http://opaquenamespace.org/ns/descriptionDepositor") do |index|
  564. # index.as :stored_searchable
  565. # end
  566. # END These are ALL the metadata from Dspace
  567. # accessor attribute used only to group the nested_geo fields and allow proper ordering in the forms
  568. 4 attr_accessor :geo_section
  569. # accessor attribute used only to allow validators to check selected options depending on current_user role
  570. 4 attr_accessor :current_username
  571. 4 class_attribute :controlled_properties
  572. #self.controlled_properties = [:based_near]
  573. 4 self.controlled_properties = []
  574. 4 accepts_nested_attributes_for :based_near, allow_destroy: true, reject_if: proc { |a| a[:id].blank? }
  575. # accepts_nested_attributes_for :nested_geo, :allow_destroy => true, :reject_if => :all_blank
  576. # accepts_nested_attributes_for :nested_related_items, :allow_destroy => true, :reject_if => :all_blank
  577. end
  578. end
  579. end

app/models/concerns/deepblue/doi_behavior.rb

38.46% lines covered

26 relevant lines. 10 lines covered and 16 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 class DoiError < RuntimeError
  4. end
  5. 1 module DoiBehavior
  6. 1 DOI_MINTING_ENABLED = true
  7. 1 DOI_PENDING = 'doi_pending'
  8. 1 DOI_MINIMUM_FILE_COUNT = 1
  9. 1 def doi_minted?
  10. !doi.nil?
  11. rescue
  12. nil
  13. end
  14. 1 def doi_minting_enabled?
  15. ::Deepblue::DoiBehavior::DOI_MINTING_ENABLED
  16. end
  17. 1 def doi_pending?
  18. doi == DOI_PENDING
  19. end
  20. 1 def doi_mint( current_user: nil, event_note: '', enforce_minimum_file_count: true, job_delay: 0 )
  21. Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  22. Deepblue::LoggingHelper.called_from,
  23. "work.id=#{id}",
  24. "doi=#{doi}",
  25. "current_user=#{current_user}",
  26. "event_note=#{event_note}",
  27. "enforce_minimum_file_count=#{enforce_minimum_file_count}",
  28. "job_delay=#{job_delay}" ]
  29. return false if doi_pending?
  30. # Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  31. # Deepblue::LoggingHelper.called_from,
  32. # "work.id=#{id}",
  33. # "past doi_pending?" ]
  34. return false if doi_minted?
  35. # Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  36. # Deepblue::LoggingHelper.called_from,
  37. # "work.id=#{id}",
  38. # "past doi_minted?" ]
  39. return false if enforce_minimum_file_count && file_sets.count < DOI_MINIMUM_FILE_COUNT
  40. self.doi = DOI_PENDING
  41. self.save
  42. self.reload
  43. current_user = current_user.email if current_user.respond_to? :email
  44. Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  45. Deepblue::LoggingHelper.called_from,
  46. "work.id=#{id}",
  47. "doi=#{doi}",
  48. "about to call DoiMintingJob" ]
  49. ::DoiMintingJob.perform_later( id, current_user: current_user, job_delay: job_delay )
  50. return true
  51. rescue Exception => e # rubocop:disable Lint/RescueException
  52. Rails.logger.error "DoiBehavior.doi_mint for curation_concern.id #{id} -- #{e.class}: #{e.message} at #{e.backtrace[0]}"
  53. end
  54. end
  55. end

app/models/concerns/deepblue/email_behavior.rb

31.01% lines covered

129 relevant lines. 40 lines covered and 89 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 require_relative './abstract_event_behavior'
  4. 1 class EmailError < AbstractEventError
  5. end
  6. 1 module EmailBehavior
  7. 1 include AbstractEventBehavior
  8. 1 def attributes_all_for_email
  9. %i[]
  10. end
  11. 1 def attributes_brief_for_email
  12. %i[]
  13. end
  14. 1 def attributes_standard_for_email
  15. %i[]
  16. end
  17. 1 def attributes_for_email_rds_create
  18. return attributes_standard_for_email, USE_BLANK_KEY_VALUES
  19. end
  20. 1 def attributes_for_email_rds_destroy
  21. return attributes_standard_for_email, USE_BLANK_KEY_VALUES
  22. end
  23. 1 def attributes_for_email_rds_globus
  24. return attributes_brief_for_email, IGNORE_BLANK_KEY_VALUES
  25. end
  26. 1 def attributes_for_email_rds_publish
  27. return attributes_standard_for_email, USE_BLANK_KEY_VALUES
  28. end
  29. 1 def attributes_for_email_rds_unpublish
  30. return attributes_standard_for_email, USE_BLANK_KEY_VALUES
  31. end
  32. 1 def attributes_for_email_user_create
  33. attributes_standard_for_email
  34. end
  35. 1 def email_attribute_values_for_snapshot( attributes:,
  36. current_user:,
  37. event:,
  38. event_note:,
  39. to_note:,
  40. ignore_blank_key_values:,
  41. **added_email_key_values )
  42. email_key_values = { user_email: for_email_user( current_user ) }
  43. email_key_values.merge!( event_note: event_note ) if event_note.present?
  44. email_key_values.merge!( to_note: to_note ) if to_note.present?
  45. email_key_values.merge!( added_email_key_values ) if added_email_key_values.present?
  46. email_key_values = map_email_attributes!( event: event,
  47. attributes: attributes,
  48. ignore_blank_key_values: ignore_blank_key_values,
  49. **email_key_values )
  50. email_key_values
  51. end
  52. 1 def email_address_rds
  53. rv = EmailHelper.notification_email # will be nil on developer's machine
  54. rv
  55. end
  56. 1 def email_address_rds_deepblue
  57. rv = EmailHelper.contact_email
  58. rv
  59. end
  60. 1 def email_address_user( current_user )
  61. rv = EmailHelper.user_email_from current_user
  62. rv
  63. end
  64. 1 def email_compose_body( message:, email_key_values: )
  65. body = StringIO.new
  66. body.puts message.to_s if message.present?
  67. email_key_values.each_pair do |key, value|
  68. label = for_email_label key
  69. value = for_email_value( key, value )
  70. body.puts "#{label}#{value}"
  71. end
  72. body.string
  73. end
  74. 1 def email_rds_create( current_user:, event_note: '', return_email_parameters: false, send_it: true )
  75. attributes, ignore_blank_key_values = attributes_for_email_rds_create
  76. email_key_values = {}
  77. email_key_values = map_email_attributes!( event: EVENT_CREATE,
  78. attributes: attributes,
  79. ignore_blank_key_values: ignore_blank_key_values,
  80. **email_key_values )
  81. email_event_notification( to: email_address_rds,
  82. to_note: 'RDS',
  83. from: email_address_rds,
  84. subject: Deepblue::EmailHelper.t( "hyrax.email.subject.work_created" ),
  85. attributes: attributes,
  86. current_user: current_user,
  87. event: EVENT_CREATE,
  88. event_note: event_note,
  89. id: for_email_id,
  90. ignore_blank_key_values: ignore_blank_key_values,
  91. return_email_parameters: return_email_parameters,
  92. send_it: send_it,
  93. email_key_values: email_key_values )
  94. end
  95. 1 def email_rds_destroy( current_user:, event_note: '' )
  96. attributes, ignore_blank_key_values = attributes_for_email_rds_destroy
  97. email_event_notification( to: email_address_rds,
  98. to_note: 'RDS',
  99. from: email_address_rds,
  100. subject: Deepblue::EmailHelper.t( "hyrax.email.subject.work_deleted" ),
  101. attributes: attributes,
  102. current_user: current_user,
  103. event: EVENT_DESTROY,
  104. event_note: event_note,
  105. id: for_email_id,
  106. ignore_blank_key_values: ignore_blank_key_values )
  107. end
  108. 1 def email_rds_globus( current_user:, event_note: )
  109. attributes, ignore_blank_key_values = attributes_for_email_rds_globus
  110. email_event_notification( to: email_address_rds,
  111. to_note: 'RDS',
  112. from: email_address_rds,
  113. subject: for_email_subject( subject_rest: "Globus #{event_note}" ),
  114. attributes: attributes,
  115. current_user: current_user,
  116. event: EVENT_GLOBUS,
  117. event_note: event_note,
  118. id: for_email_id,
  119. ignore_blank_key_values: ignore_blank_key_values )
  120. end
  121. 1 def email_rds_publish( current_user:, event_note: '', message: '' )
  122. attributes, ignore_blank_key_values = attributes_for_email_rds_publish
  123. email_event_notification( to: email_address_rds,
  124. to_note: 'RDS',
  125. from: email_address_rds,
  126. subject: Deepblue::EmailHelper.t( "hyrax.email.subject.work_published" ),
  127. attributes: attributes,
  128. current_user: current_user,
  129. event: EVENT_PUBLISH,
  130. event_note: event_note,
  131. message: message,
  132. id: for_email_id,
  133. ignore_blank_key_values: ignore_blank_key_values )
  134. end
  135. 1 def email_rds_unpublish( current_user:, event_note: '' )
  136. attributes, ignore_blank_key_values = attributes_for_email_rds_unpublish
  137. email_event_notification( to: email_address_rds,
  138. to_note: 'RDS',
  139. from: email_address_rds,
  140. subject: Deepblue::EmailHelper.t( "hyrax.email.subject.work_unpublished" ),
  141. attributes: attributes,
  142. current_user: current_user,
  143. event: EVENT_UNPUBLISH,
  144. event_note: event_note,
  145. id: for_email_id,
  146. ignore_blank_key_values: ignore_blank_key_values )
  147. end
  148. 1 def email_user_create( current_user:, event_note: '' )
  149. email_event_notification( to: email_address_user( current_user ),
  150. to_note: 'user',
  151. from: email_address_rds,
  152. subject: Deepblue::EmailHelper.t( "hyrax.email.subject.work_created" ),
  153. attributes: attributes_for_email_user_create,
  154. current_user: current_user,
  155. event: EVENT_CREATE,
  156. event_note: event_note,
  157. id: for_email_id,
  158. ignore_blank_key_values: false )
  159. end
  160. 1 def email_create_to_user( current_user:, event_note: '' ) # TODO: delete this method
  161. email_create( current_user: current_user, event_note: event_note )
  162. end
  163. 1 def for_email_class
  164. for_email_object.class
  165. end
  166. 1 def for_email_id
  167. for_email_object.id
  168. end
  169. 1 def for_email_ignore_empty_attributes
  170. true
  171. end
  172. 1 def for_email_label( key )
  173. "#{key}: "
  174. end
  175. 1 def for_email_object
  176. self
  177. end
  178. 1 def for_email_route
  179. "route to #{for_email_object.id}"
  180. end
  181. 1 def for_email_subject( subject_rest: )
  182. "DBD: #{subject_rest}"
  183. end
  184. 1 def for_email_value( key, value )
  185. return '' if value.blank?
  186. if value.respond_to? :each
  187. value = if 1 == value.size
  188. value[0]
  189. else
  190. value.join( for_email_value_sep( key: key ) )
  191. end
  192. end
  193. value
  194. end
  195. 1 def for_email_value_sep( key: )
  196. rv = case key.to_s
  197. when 'title'
  198. ' '
  199. else
  200. '; '
  201. end
  202. rv
  203. end
  204. 1 def for_email_user( current_user )
  205. return '' if current_user.blank?
  206. return current_user if current_user.is_a? String
  207. EmailHelper.user_email_from( current_user )
  208. end
  209. 1 def map_email_attributes!( event:, attributes:, ignore_blank_key_values:, **email_key_values )
  210. prov_object = for_email_object
  211. if attributes.present?
  212. attributes.each do |attribute|
  213. next if map_email_attributes_override!( event: event,
  214. attribute: attribute,
  215. ignore_blank_key_values: ignore_blank_key_values,
  216. email_key_values: email_key_values )
  217. value = case attribute.to_s
  218. when 'id'
  219. for_email_id
  220. when 'location'
  221. for_email_route
  222. when 'route'
  223. for_email_route
  224. when 'date_created'
  225. prov_object[:date_created].blank? ? '' : prov_object[:date_created]
  226. else
  227. prov_object[attribute]
  228. end
  229. value = '' if value.nil?
  230. if ignore_blank_key_values
  231. email_key_values[attribute] = value if value.present?
  232. else
  233. email_key_values[attribute] = value
  234. end
  235. end
  236. end
  237. email_key_values
  238. end
  239. # override this if there is anything extra to add
  240. # return true if handled
  241. 1 def map_email_attributes_override!( event:, # rubocop:disable Lint/UnusedMethodArgument
  242. attribute:, # rubocop:disable Lint/UnusedMethodArgument
  243. ignore_blank_key_values:, # rubocop:disable Lint/UnusedMethodArgument
  244. email_key_values: ) # rubocop:disable Lint/UnusedMethodArgument
  245. handled = false
  246. return handled
  247. end
  248. 1 protected
  249. 1 def email_event_notification( to:,
  250. to_note:,
  251. from:,
  252. subject:,
  253. attributes:,
  254. current_user:,
  255. event:,
  256. event_note:,
  257. message: '',
  258. ignore_blank_key_values:,
  259. id:,
  260. return_email_parameters: false,
  261. send_it: true,
  262. email_key_values: nil )
  263. if email_key_values.blank?
  264. email_key_values = email_attribute_values_for_snapshot( attributes: attributes,
  265. current_user: current_user,
  266. event: event,
  267. event_note: event_note,
  268. to_note: to_note,
  269. ignore_blank_key_values: ignore_blank_key_values )
  270. end
  271. event_attributes_cache_write( event: event, id: id, behavior: :EmailBehavior )
  272. body = email_compose_body( message: message, email_key_values: email_key_values )
  273. EmailHelper.send_email( to: to, from: from, subject: subject, body: body ) if send_it
  274. class_name = for_email_class.name
  275. EmailHelper.log( class_name: class_name,
  276. current_user: current_user,
  277. event: event,
  278. event_note: event_note,
  279. id: id,
  280. to: to,
  281. from: from,
  282. subject: subject,
  283. message: message,
  284. body: body,
  285. **email_key_values ) if send_it
  286. return nil unless return_email_parameters
  287. parameters = { to: to,
  288. to_note: to_note,
  289. from: from,
  290. subject: subject,
  291. message: message,
  292. body: body,
  293. current_user: current_user,
  294. event: event,
  295. event_note: event_note,
  296. id: id,
  297. email_key_values: email_key_values }
  298. return parameters
  299. end
  300. end
  301. end

app/models/concerns/deepblue/embargoable_behavior.rb

32.56% lines covered

43 relevant lines. 14 lines covered and 29 lines missed.
    
  1. # don't freeze, it causes errors
  2. # require File.join(Gem::Specification.find_by_name("hydra-access-controls").full_gem_path, "app/models/concerns/hydra/access_controls/embargoable_behavior.rb")
  3. 1 module Deepblue
  4. # monkey patch Embargoable#deactivate_embargo!
  5. 1 module EmbargoableBehavior
  6. 1 extend ActiveSupport::Concern
  7. 1 included do
  8. 2 alias_method :monkey_deactivate_embargo!, :deactivate_embargo!
  9. 2 alias_method :monkey_deactivate_lease!, :deactivate_lease!
  10. end
  11. # Deactivates the embargo and logs a message to the embargo object.
  12. # Marks this record as dirty so that it will get reindexed.
  13. 1 def deactivate_embargo!( current_user: nil )
  14. return if embargo.nil?
  15. # embargo.deactivate! whipes out work.visibility_after_embargo before it can be applied, so save it and apply it
  16. vis_after = visibility_after_embargo
  17. vis_after = visibility_after_embargo_default if vis_after.nil?
  18. provenance_unembargo( current_user: Deepblue::ProvenanceHelper.system_as_current_user,
  19. embargo_visibility: visibility,
  20. embargo_visibility_after: vis_after )
  21. # Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  22. # Deepblue::LoggingHelper.called_from,
  23. # "before",
  24. # "vis_after=#{vis_after}",
  25. # "id=#{id}",
  26. # "embargo_release_date=#{embargo_release_date}",
  27. # "visibility=#{visibility}",
  28. # "visibility_during_embargo=#{visibility_during_embargo}",
  29. # "visibility_after_embargo=#{visibility_after_embargo}" ]
  30. embargo.deactivate!
  31. # Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  32. # Deepblue::LoggingHelper.called_from,
  33. # "after",
  34. # "id=#{id}",
  35. # "embargo_release_date=#{embargo_release_date}",
  36. # "visibility=#{visibility}",
  37. # "visibility_during_embargo=#{visibility_during_embargo}",
  38. # "visibility_after_embargo=#{visibility_after_embargo}" ]
  39. self.visibility = vis_after
  40. visibility_will_change!
  41. end
  42. 1 def deactivate_lease!
  43. return if lease.nil?
  44. # lease.deactivate! whipes out work.visibility_after_lease before it can be applied, so save it and apply
  45. vis_after = visibility_after_lease
  46. vis_after = visibility_after_lease_default if vis_after.nil?
  47. lease.deactivate!
  48. self.visibility = vis_after
  49. visibility_will_change!
  50. end
  51. # Set the current visibility to match what is described in the embargo.
  52. 1 def embargo_visibility!
  53. return unless embargo_release_date
  54. if under_embargo?
  55. self.visibility_during_embargo = visibility_during_embargo ? visibility_during_embargo : visibility_during_embargo_default
  56. self.visibility_after_embargo = visibility_after_embargo ? visibility_after_embargo : visibility_after_embargo_default
  57. self.visibility = visibility_during_embargo
  58. else
  59. self.visibility = visibility_after_embargo ? visibility_after_embargo : visibility_after_embargo_default
  60. end
  61. end
  62. # Set the current visibility to match what is described in the lease.
  63. 1 def lease_visibility!
  64. if lease_expiration_date
  65. if active_lease?
  66. self.visibility_during_lease = visibility_during_lease ? visibility_during_lease : visibility_during_lease_default
  67. self.visibility_after_lease = visibility_after_lease ? visibility_after_lease : visibility_after_lease_default
  68. self.visibility = visibility_during_lease
  69. else
  70. self.visibility = visibility_after_lease ? visibility_after_lease : visibility_after_lease_default
  71. end
  72. end
  73. end
  74. 1 def visibility_after_embargo_default
  75. ::DeepBlueDocs::Application.config.embargo_visibility_after_default_status
  76. end
  77. 1 def visibility_after_lease_default
  78. ::Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
  79. end
  80. 1 def visibility_during_embargo_default
  81. ::DeepBlueDocs::Application.config.embargo_visibility_during_default_status
  82. end
  83. 1 def visibility_during_lease_default
  84. ::Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED
  85. end
  86. end
  87. end

app/models/concerns/deepblue/file_set_behavior.rb

32.84% lines covered

67 relevant lines. 22 lines covered and 45 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 require_relative '../../../services/deepblue/virus_scan_service'
  4. 1 module FileSetBehavior
  5. 1 extend ActiveSupport::Concern
  6. 1 include ::Deepblue::VirusScanService
  7. 1 included do
  8. 1 after_initialize :set_deepblue_file_set_defaults
  9. 1 def set_deepblue_file_set_defaults
  10. 21 return unless new_record?
  11. # self.file_size = 0
  12. # self.visibility = 'open'
  13. end
  14. end
  15. # versioning
  16. 1 def versions
  17. ofile = original_file
  18. return [] if ofile.nil?
  19. rv = ofile.versions
  20. return [] if rv.nil?
  21. rv = rv.all
  22. end
  23. 1 def latest_version
  24. versions.last
  25. end
  26. 1 def latest_version_create_datetime
  27. version_datetime latest_version
  28. end
  29. 1 def version_count
  30. vers = versions
  31. return 0 if vers.nil?
  32. vers.count
  33. end
  34. 1 def version_datetime( version )
  35. return nil if version.nil?
  36. return '' if version.created.blank?
  37. DateTime.parse version.created
  38. end
  39. 1 def version_datetime_display( version )
  40. timestamp = version_datetime( version )
  41. DeepblueHelper.display_timestamp timestamp
  42. end
  43. 1 def update_parent
  44. return if parent.nil?
  45. parent.total_file_size_add_file_set!( self )
  46. end
  47. # virus scanning
  48. 1 def virus_scan
  49. LoggingHelper.bold_debug [ LoggingHelper.here, LoggingHelper.called_from, "original_file = #{original_file}" ]
  50. # check file size here to avoid making a temp copy of the file in VirusCheckerService
  51. needed = virus_scan_needed?
  52. if needed && virus_scan_file_too_big?
  53. virus_scan_status_update( scan_result: VIRUS_SCAN_SKIPPED_TOO_BIG )
  54. elsif needed
  55. # TODO: figure out how to retry the virus scan as this only works for ( original_file && original_file.new_record? )
  56. scan_result = Hydra::Works::VirusCheckerService.file_has_virus? original_file
  57. virus_scan_status_update( scan_result: scan_result, previous_scan_result: virus_scan_status )
  58. else
  59. logger.info "Virus scan not needed." # TODO: improve message
  60. end
  61. end
  62. 1 def virus_scan_file_too_big?
  63. fsize = virus_scan_file_size
  64. return false if fsize.blank?
  65. rv = fsize.to_i > DeepBlueDocs::Application.config.virus_scan_max_file_size
  66. return rv
  67. end
  68. 1 def virus_scan_file_size
  69. if file_size.blank?
  70. if original_file.nil?
  71. 0
  72. elsif original_file.respond_to? :size
  73. original_file.size
  74. else
  75. 0
  76. end
  77. else
  78. # file_size[0]
  79. file_size_value
  80. end
  81. end
  82. 1 def virus_scan_needed?
  83. # really, it's always needed.
  84. true
  85. # LoggingHelper.bold_debug [ LoggingHelper.here, LoggingHelper.called_from ]
  86. # return true if original_file && original_file.new_record?
  87. # return false unless DeepBlueDocs::Application.config.virus_scan_retry
  88. # scan_status = virus_scan_status
  89. # return true if scan_status.blank?
  90. # case scan_status
  91. # when VIRUS_SCAN_NOT_VIRUS
  92. # false
  93. # when VIRUS_SCAN_VIRUS
  94. # false
  95. # when VIRUS_SCAN_SKIPPED_TOO_BIG
  96. # false
  97. # when VIRUS_SCAN_SKIPPED_SERVICE_UNAVAILABLE
  98. # DeepBlueDocs::Application.config.virus_scan_retry_on_service_unavailable
  99. # when VIRUS_SCAN_ERROR
  100. # DeepBlueDocs::Application.config.virus_scan_retry_on_error
  101. # when VIRUS_SCAN_UNKNOWN
  102. # DeepBlueDocs::Application.config.virus_scan_retry_on_unknown
  103. # else
  104. # true
  105. # end
  106. end
  107. 1 def virus_scan_retry?
  108. return !( original_file && original_file.new_record? )
  109. end
  110. 1 def virus_scan_status_update( scan_result:, previous_scan_result: nil )
  111. LoggingHelper.bold_debug [ LoggingHelper.here,
  112. LoggingHelper.called_from,
  113. "scan_result=#{scan_result}",
  114. "previous_scan_result=#{previous_scan_result}" ]
  115. # Oops. Really don't want to consider previous result as we want the new timestamp
  116. # return scan_result if previous_scan_result.present? && scan_result == previous_scan_result
  117. # for some reason, this does not save the attributes
  118. # virus_scan_service = virus_scan_service_name
  119. # virus_scan_status = scan_result
  120. # virus_scan_status_date = virus_scan_timestamp_now
  121. # but this does save the attributes
  122. self['virus_scan_service'] = virus_scan_service_name
  123. self['virus_scan_status'] = scan_result
  124. self['virus_scan_status_date'] = virus_scan_timestamp_now
  125. save! # ( validate: false )
  126. provenance_virus_scan( scan_result: scan_result ) # if respond_to? :provenance_virus_scan
  127. return scan_result
  128. end
  129. end
  130. end

app/models/concerns/deepblue/file_set_metadata.rb

100.0% lines covered

28 relevant lines. 28 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 module FileSetMetadata
  4. 1 extend ActiveSupport::Concern
  5. 1 included do
  6. 1 property :curation_notes_admin, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#curation_notes_admin'), multiple: true do |index|
  7. 2 index.type :text
  8. 2 index.as :stored_searchable
  9. end
  10. 1 property :curation_notes_admin_ordered, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#curation_notes_admin_ordered'), multiple: false do |index|
  11. 2 index.type :text
  12. 2 index.as :stored_searchable
  13. end
  14. 1 property :curation_notes_user, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#curation_notes_user'), multiple: true do |index|
  15. 2 index.type :text
  16. 2 index.as :stored_searchable
  17. end
  18. 1 property :curation_notes_user_ordered, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#curation_notes_user_ordered'), multiple: false do |index|
  19. 2 index.type :text
  20. 2 index.as :stored_searchable
  21. end
  22. # property :file_size, predicate: ::RDF::Vocab::DC.SizeOrDuration, multiple: false
  23. 1 property :file_size, predicate: ::RDF::Vocab::DC.SizeOrDuration, multiple: true
  24. 1 property :prior_identifier, predicate: ActiveFedora::RDF::Fcrepo::Model.altIds, multiple: true do |index|
  25. 2 index.as :stored_searchable
  26. end
  27. # TODO: can't use the same predicate twice
  28. # property :total_file_size_human_readable, predicate: ::RDF::Vocab::DC.SizeOrDuration, multiple: false
  29. 1 property :virus_scan_service, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#virus_scan_service'), multiple: false do |index|
  30. 2 index.type :text
  31. 2 index.as :stored_searchable
  32. end
  33. 1 property :virus_scan_status, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#virus_scan_status'), multiple: false do |index|
  34. 2 index.type :text
  35. 2 index.as :stored_searchable
  36. end
  37. 1 property :virus_scan_status_date, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#virus_scan_status_date'), multiple: false do |index|
  38. 2 index.type :text
  39. 2 index.as :stored_searchable
  40. end
  41. end
  42. end
  43. end

app/models/concerns/deepblue/metadata_behavior.rb

55.32% lines covered

94 relevant lines. 52 lines covered and 42 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 class MetadataError < RuntimeError
  4. end
  5. 1 module MetadataBehavior
  6. 1 METADATA_FIELD_SEP = '; '
  7. 1 METADATA_REPORT_DEFAULT_DEPTH = 2
  8. 1 METADATA_REPORT_DEFAULT_FILENAME_POST = '_metadata_report'
  9. 1 METADATA_REPORT_DEFAULT_FILENAME_EXT = '.txt'
  10. 1 def for_metadata_id
  11. 6 self.id
  12. end
  13. 1 def for_metadata_route
  14. "route to #{id}"
  15. end
  16. 1 def for_metadata_title
  17. 4 self.title
  18. end
  19. 1 def metadata_keys_all
  20. 1 %i[]
  21. end
  22. 1 def metadata_keys_report
  23. 1 %i[]
  24. end
  25. 1 def metadata_keys_brief
  26. 1 %i[]
  27. end
  28. 1 def metadata_hash( metadata_keys:, ignore_blank_values:, **key_values )
  29. 6 return {} if metadata_keys.blank?
  30. 4 key_values = {} if key_values.nil?
  31. 4 metadata_keys.each do |key|
  32. 10 next if metadata_hash_override( key: key, ignore_blank_values: ignore_blank_values, key_values: key_values )
  33. 8 value = case key.to_s
  34. when 'id'
  35. 4 for_metadata_id
  36. when 'location'
  37. for_metadata_route
  38. when 'route'
  39. for_metadata_route
  40. when 'title'
  41. 4 for_metadata_title
  42. when 'visibility'
  43. metadata_report_visibility_value( self.visibility )
  44. else
  45. self[key]
  46. end
  47. 8 value = '' if value.nil?
  48. 8 if ignore_blank_values
  49. key_values[key] = value if value.present?
  50. else
  51. 8 key_values[key] = value
  52. end
  53. end
  54. 4 key_values
  55. end
  56. # override this if there is anything extra to add
  57. # return true if handled
  58. 1 def metadata_hash_override( key:, ignore_blank_values:, key_values: ) # rubocop:disable Lint/UnusedMethodArgument
  59. 1 handled = false
  60. 1 return handled
  61. end
  62. 1 def metadata_report( dir: nil,
  63. out: nil,
  64. depth: METADATA_REPORT_DEFAULT_DEPTH,
  65. filename_pre: '',
  66. filename_post: METADATA_REPORT_DEFAULT_FILENAME_POST,
  67. filename_ext: METADATA_REPORT_DEFAULT_FILENAME_EXT )
  68. raise MetadataError, "Either dir: or out: must be specified." if dir.nil? && out.nil?
  69. if out.nil?
  70. target_file = metadata_report_filename( pathname_dir: dir,
  71. filename_pre: filename_pre,
  72. filename_post: filename_post,
  73. filename_ext: filename_ext )
  74. open( target_file, 'w' ) do |out2|
  75. metadata_report( out: out2, depth: depth )
  76. end
  77. return target_file
  78. else
  79. report_title = metadata_report_title( depth: depth )
  80. out.puts report_title
  81. ignore_blank_values, metadata_keys = metadata_report_keys
  82. metadata = metadata_hash( metadata_keys: metadata_keys, ignore_blank_values: ignore_blank_values )
  83. metadata_report_to( out: out, metadata_hash: metadata, depth: depth )
  84. # Don't include metadata reports for contained objects, such as file_sets
  85. # contained_objects = metadata_report_contained_objects
  86. # if contained_objects.count.positive?
  87. # contained_objects.each do |obj|
  88. # next unless obj.respond_to? :metadata_report
  89. # out.puts
  90. # obj.metadata_report( out: out, depth: depth + 1 )
  91. # end
  92. # end
  93. return nil
  94. end
  95. end
  96. 1 def metadata_report_contained_objects
  97. 1 []
  98. end
  99. 1 def metadata_report_filename( pathname_dir:,
  100. filename_pre:,
  101. filename_post: METADATA_REPORT_DEFAULT_FILENAME_POST,
  102. filename_ext: METADATA_REPORT_DEFAULT_FILENAME_EXT )
  103. 2 pathname_dir.join "#{filename_pre}#{for_metadata_id}#{filename_post}#{filename_ext}"
  104. end
  105. 1 def metadata_report_keys
  106. 1 return AbstractEventBehavior::IGNORE_BLANK_KEY_VALUES, metadata_keys_report
  107. end
  108. 1 def metadata_report_label( metadata_key:, metadata_value: )
  109. return nil if metadata_key.blank?
  110. label = metadata_report_label_override(metadata_key: metadata_key, metadata_value: metadata_value )
  111. return label if label.present?
  112. label = case metadata_key.to_s
  113. when 'id'
  114. 'ID: '
  115. when 'location'
  116. 'Location: '
  117. when 'route'
  118. 'Route: '
  119. when 'title'
  120. 'Title: '
  121. when 'visibility'
  122. 'Visibility: '
  123. else
  124. "#{metadata_key.to_s.titlecase}: "
  125. end
  126. label
  127. end
  128. # override this if there is anything extra to add
  129. # return nil if not handled
  130. 1 def metadata_report_label_override( metadata_key:, metadata_value: ) # rubocop:disable Lint/UnusedMethodArgument
  131. 1 label = nil
  132. 1 return label
  133. end
  134. 1 def metadata_report_title( depth:,
  135. header_begin: '=',
  136. header_end: '=' )
  137. report_title = for_metadata_title
  138. report_title = report_title.join( metadata_report_title_field_sep ) if report_title.respond_to? :join
  139. if depth.positive?
  140. "#{header_begin * depth} #{metadata_report_title_pre}#{report_title} #{header_end * depth}"
  141. else
  142. "#{metadata_report_title_pre}#{report_title}"
  143. end
  144. end
  145. 1 def metadata_report_title_pre
  146. 1 ''
  147. end
  148. 1 def metadata_report_title_field_sep
  149. 1 ' '
  150. end
  151. 1 def metadata_report_to( out:, metadata_hash:, depth: 0 )
  152. return if out.nil?
  153. metadata_hash.each_pair do |key, value|
  154. metadata_report_item_to( out: out, key: key, value: value, depth: depth )
  155. end
  156. end
  157. 1 def metadata_report_item_to( out:, key:, value:, depth: ) # rubocop:disable Lint/UnusedMethodArgument
  158. label = metadata_report_label(metadata_key: key, metadata_value: value )
  159. MetadataHelper.report_item( out, label, value )
  160. end
  161. 1 def metadata_report_visibility_value( visibility )
  162. case visibility
  163. when Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
  164. 'published'
  165. when Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
  166. 'private'
  167. else
  168. visibility
  169. end
  170. end
  171. end
  172. end

app/models/concerns/deepblue/provenance_behavior.rb

49.06% lines covered

265 relevant lines. 130 lines covered and 135 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 require_relative './abstract_event_behavior'
  4. 1 class ProvenanceLogError < AbstractEventError
  5. end
  6. 1 module ProvenanceBehavior
  7. 1 include AbstractEventBehavior
  8. 1 def attributes_all_for_provenance
  9. %i[]
  10. end
  11. 1 def attributes_brief_for_provenance
  12. %i[]
  13. end
  14. 1 def attributes_virus_for_provenance
  15. attributes_brief_for_provenance
  16. end
  17. 1 def attributes_update_for_provenance
  18. attributes_all_for_provenance
  19. end
  20. 1 def attributes_for_provenance_add
  21. return attributes_brief_for_provenance, IGNORE_BLANK_KEY_VALUES
  22. end
  23. 1 def attributes_for_provenance_characterize
  24. return attributes_brief_for_provenance, IGNORE_BLANK_KEY_VALUES
  25. end
  26. 1 def attributes_for_provenance_create
  27. return attributes_all_for_provenance, USE_BLANK_KEY_VALUES
  28. end
  29. 1 def attributes_for_provenance_create_derivative
  30. return attributes_brief_for_provenance, USE_BLANK_KEY_VALUES
  31. end
  32. 1 def attributes_for_provenance_destroy
  33. return attributes_all_for_provenance, USE_BLANK_KEY_VALUES
  34. end
  35. 1 def attributes_for_provenance_embargo
  36. return attributes_all_for_provenance, USE_BLANK_KEY_VALUES
  37. end
  38. 1 def attributes_for_provenance_fixity_check
  39. return attributes_brief_for_provenance, IGNORE_BLANK_KEY_VALUES
  40. end
  41. 1 def attributes_for_provenance_ingest
  42. return attributes_all_for_provenance, USE_BLANK_KEY_VALUES
  43. end
  44. 1 def attributes_for_provenance_migrate
  45. return attributes_brief_for_provenance, IGNORE_BLANK_KEY_VALUES
  46. end
  47. 1 def attributes_for_provenance_mint_doi
  48. 2 return attributes_all_for_provenance, USE_BLANK_KEY_VALUES
  49. end
  50. 1 def attributes_for_provenance_publish
  51. 2 return attributes_all_for_provenance, USE_BLANK_KEY_VALUES
  52. end
  53. 1 def attributes_for_provenance_tombstone
  54. return attributes_all_for_provenance, USE_BLANK_KEY_VALUES
  55. end
  56. 1 def attributes_for_provenance_unembargo
  57. return attributes_all_for_provenance, USE_BLANK_KEY_VALUES
  58. end
  59. 1 def attributes_for_provenance_unpublish
  60. 2 return attributes_all_for_provenance, USE_BLANK_KEY_VALUES
  61. end
  62. 1 def attributes_for_provenance_update
  63. 2 return attributes_update_for_provenance, IGNORE_BLANK_KEY_VALUES
  64. end
  65. 1 def attributes_for_provenance_update_version
  66. return attributes_update_for_provenance, IGNORE_BLANK_KEY_VALUES
  67. end
  68. 1 def attributes_for_provenance_upload
  69. return attributes_all_for_provenance, USE_BLANK_KEY_VALUES
  70. end
  71. 1 def attributes_for_provenance_virus_scan
  72. return attributes_virus_for_provenance, IGNORE_BLANK_KEY_VALUES
  73. end
  74. 1 def attributes_for_provenance_workflow
  75. return attributes_brief_for_provenance, IGNORE_BLANK_KEY_VALUES
  76. end
  77. 1 def attributes_cache_fetch( event:, id: for_provenance_id )
  78. key = attributes_cache_key( event: event, id: id )
  79. rv = Rails.cache.fetch( key )
  80. rv
  81. end
  82. 1 def attributes_cache_key( event:, id: )
  83. "#{id}.#{event}"
  84. end
  85. 1 def attributes_cache_write( event:, id: for_provenance_id, attributes: )
  86. key = attributes_cache_key( event: event, id: id )
  87. Rails.cache.write( key, attributes )
  88. end
  89. 1 def for_provenance_event_cache_exist?( event:, id: for_provenance_id )
  90. key = for_provenance_event_cache_key( event: event, id: id )
  91. rv = Rails.cache.exist?( key )
  92. rv
  93. end
  94. 1 def for_provenance_event_cache_fetch( event:, id: for_provenance_id )
  95. key = for_provenance_event_cache_key( event: event, id: id )
  96. rv = Rails.cache.fetch( key )
  97. rv
  98. end
  99. 1 def for_provenance_event_cache_key( event:, id: )
  100. 1 "#{id}.#{event}.provenance"
  101. end
  102. 1 def for_provenance_event_cache_write( event:, id: for_provenance_id, value: DateTime.now )
  103. 1 key = for_provenance_event_cache_key( event: event, id: id )
  104. 1 Rails.cache.write( key, value, expires_in: 12.hours )
  105. end
  106. 1 def for_provenance_class
  107. 1 for_provenance_object.class
  108. end
  109. 1 def for_provenance_id
  110. 3 for_provenance_object.id
  111. end
  112. 1 def for_provenance_ignore_empty_attributes
  113. true
  114. end
  115. 1 def for_provenance_object
  116. 10 self
  117. end
  118. 1 def for_provenance_route
  119. "route to #{for_provenance_object.id}"
  120. end
  121. 1 def for_provenance_user( current_user )
  122. 4 return '' if current_user.blank?
  123. 4 return current_user if current_user.is_a? String
  124. EmailHelper.user_email_from( current_user )
  125. end
  126. 1 def map_provenance_attributes!( event:, attributes:, ignore_blank_key_values:, **prov_key_values )
  127. 4 prov_object = for_provenance_object
  128. # prov_object_class = prov_object.class.name
  129. 4 if attributes.present?
  130. 4 attributes.each do |attribute|
  131. 48 next if map_provenance_attributes_override!( event: event,
  132. attribute: attribute,
  133. ignore_blank_key_values: ignore_blank_key_values,
  134. prov_key_values: prov_key_values )
  135. 44 value = case attribute.to_s
  136. when 'id'
  137. for_provenance_id
  138. when 'location'
  139. for_provenance_route
  140. when 'route'
  141. for_provenance_route
  142. when 'date_created'
  143. 3 prov_object[:date_created].blank? ? '' : prov_object[:date_created]
  144. else
  145. 41 if prov_object.has_attribute? attribute
  146. 41 prov_object[attribute]
  147. else
  148. 'MISSING_ATTRIBUTE'
  149. end
  150. # begin
  151. # prov_object[attribute]
  152. # rescue Exception => e
  153. # puts "attribute='#{attribute}' #{e}"
  154. # raise e
  155. # end
  156. end
  157. 44 value = '' if value.nil?
  158. 44 if ignore_blank_key_values
  159. 2 prov_key_values[attribute] = value if value.present?
  160. else
  161. 42 prov_key_values[attribute] = value
  162. end
  163. end
  164. end
  165. 1 prov_key_values
  166. end
  167. 1 def map_provenance_attributes_for_update( current_user, event_note, provenance_attribute_values_before_update )
  168. # Rails.logger.debug ">>>>>>"
  169. # Rails.logger.debug "map_provenance_attributes_for_update"
  170. # Rails.logger.debug "provenance_attribute_values_before_update=#{ActiveSupport::JSON.encode provenance_attribute_values_before_update}"
  171. # Rails.logger.debug ">>>>>>"
  172. return nil if provenance_attribute_values_before_update.blank?
  173. attributes, ignore_blank_key_values = attributes_for_provenance_update
  174. prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  175. current_user: current_user,
  176. event: EVENT_UPDATE,
  177. event_note: event_note,
  178. ignore_blank_key_values: ignore_blank_key_values )
  179. # only the changed values
  180. # Rails.logger.debug ">>>>>>"
  181. # Rails.logger.debug "map_provenance_attributes_for_update"
  182. # Rails.logger.debug "before reject=#{ActiveSupport::JSON.encode prov_key_values}"
  183. # Rails.logger.debug ">>>>>>"
  184. prov_key_values.reject! { |attribute, value| value == provenance_attribute_values_before_update[attribute] }
  185. # Rails.logger.debug ">>>>>>"
  186. # Rails.logger.debug "map_provenance_attributes_for_update"
  187. # Rails.logger.debug "after reject=#{ActiveSupport::JSON.encode prov_key_values}"
  188. # Rails.logger.debug ">>>>>>"
  189. prov_key_values
  190. end
  191. # override this if there is anything extra to add
  192. # return true if handled
  193. 1 def map_provenance_attributes_override!( event:, # rubocop:disable Lint/UnusedMethodArgument
  194. attribute:, # rubocop:disable Lint/UnusedMethodArgument
  195. ignore_blank_key_values:, # rubocop:disable Lint/UnusedMethodArgument
  196. prov_key_values: ) # rubocop:disable Lint/UnusedMethodArgument
  197. handled = false
  198. return handled
  199. end
  200. 1 def provenance_attribute_values_for_snapshot( attributes:,
  201. current_user:,
  202. event:,
  203. event_note:,
  204. ignore_blank_key_values:,
  205. **added_prov_key_values )
  206. 4 prov_key_values = ProvenanceHelper.logger_initialize_key_values(user_email: for_provenance_user(current_user ),
  207. event_note: event_note,
  208. **added_prov_key_values )
  209. 4 prov_key_values = map_provenance_attributes!( event: event,
  210. attributes: attributes,
  211. ignore_blank_key_values: ignore_blank_key_values,
  212. **prov_key_values )
  213. 1 prov_key_values
  214. end
  215. 1 def provenance_attribute_values_for_update( current_user:, event_note: '' )
  216. attributes, _ignore_blank_key_values = attributes_for_provenance_update
  217. provenance_attribute_values_for_snapshot( attributes: attributes,
  218. current_user: current_user,
  219. event: EVENT_UPDATE,
  220. event_note: event_note,
  221. ignore_blank_key_values: false )
  222. end
  223. 1 def provenance_characterize( current_user:, event_note: '', calling_class:, **added_prov_key_values )
  224. event = EVENT_CHARACTERIZE
  225. attributes, ignore_blank_key_values = attributes_for_provenance_add
  226. added_prov_key_values = { calling_class: calling_class }.merge added_prov_key_values
  227. prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  228. current_user: current_user,
  229. event: event,
  230. event_note: event_note,
  231. ignore_blank_key_values: ignore_blank_key_values,
  232. **added_prov_key_values )
  233. attributes, ignore_blank_key_values = attributes_for_provenance_characterize
  234. provenance_log_event( attributes: attributes,
  235. current_user: current_user,
  236. event: event,
  237. event_note: event_note,
  238. ignore_blank_key_values: ignore_blank_key_values,
  239. prov_key_values: prov_key_values )
  240. end
  241. 1 def provenance_child_add( current_user:, child_id:, event_note: '', **added_prov_key_values )
  242. event = EVENT_CHILD_ADD
  243. added_prov_key_values = { child_id: child_id }.merge added_prov_key_values
  244. attributes, ignore_blank_key_values = attributes_for_provenance_add
  245. prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  246. current_user: current_user,
  247. event: event,
  248. event_note: event_note,
  249. ignore_blank_key_values: ignore_blank_key_values,
  250. **added_prov_key_values )
  251. provenance_log_event( attributes: nil,
  252. current_user: current_user,
  253. event: event,
  254. event_note: event_note,
  255. ignore_blank_key_values: true,
  256. prov_key_values: prov_key_values )
  257. end
  258. 1 def provenance_child_remove( current_user:, child_id:, event_note: '', **added_prov_key_values )
  259. event = EVENT_CHILD_REMOVE
  260. added_prov_key_values = { child_id: child_id }.merge added_prov_key_values
  261. attributes, ignore_blank_key_values = attributes_for_provenance_add
  262. prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  263. current_user: current_user,
  264. event: event,
  265. event_note: event_note,
  266. ignore_blank_key_values: ignore_blank_key_values,
  267. **added_prov_key_values )
  268. provenance_log_event( attributes: nil,
  269. current_user: current_user,
  270. event: event,
  271. event_note: event_note,
  272. ignore_blank_key_values: true,
  273. prov_key_values: prov_key_values )
  274. end
  275. 1 def provenance_create( current_user:, event_note: '' )
  276. attributes, ignore_blank_key_values = attributes_for_provenance_create
  277. provenance_log_event( attributes: attributes,
  278. current_user: current_user,
  279. event: EVENT_CREATE,
  280. event_note: event_note,
  281. ignore_blank_key_values: ignore_blank_key_values )
  282. end
  283. 1 def provenance_create_derivative( current_user:, event_note: '', calling_class:, **added_prov_key_values )
  284. event = EVENT_CREATE_DERIVATIVE
  285. attributes, ignore_blank_key_values = attributes_for_provenance_add
  286. added_prov_key_values = { calling_class: calling_class }.merge added_prov_key_values
  287. prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  288. current_user: current_user,
  289. event: event,
  290. event_note: event_note,
  291. ignore_blank_key_values: ignore_blank_key_values,
  292. **added_prov_key_values )
  293. attributes, ignore_blank_key_values = attributes_for_provenance_create_derivative
  294. provenance_log_event( attributes: attributes,
  295. current_user: current_user,
  296. event: event,
  297. event_note: event_note,
  298. ignore_blank_key_values: ignore_blank_key_values,
  299. prov_key_values: prov_key_values )
  300. end
  301. 1 def provenance_destroy( current_user:, event_note: '' )
  302. unless DeepBlueDocs::Application.config.provenance_log_redundant_events
  303. return if for_provenance_event_cache_exist?( event: EVENT_DESTROY )
  304. end
  305. attributes, ignore_blank_key_values = attributes_for_provenance_destroy
  306. provenance_log_event( attributes: attributes,
  307. current_user: current_user,
  308. event: EVENT_DESTROY,
  309. event_note: event_note,
  310. ignore_blank_key_values: ignore_blank_key_values )
  311. end
  312. 1 def provenance_embargo( current_user:, event_note: '', **embargo_values )
  313. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  314. # ::Deepblue::LoggingHelper.called_from,
  315. # "embargo_values=#{embargo_values}",
  316. # "" ]
  317. attributes, ignore_blank_key_values = attributes_for_provenance_embargo
  318. prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  319. current_user: current_user,
  320. event: EVENT_EMBARGO,
  321. event_note: event_note,
  322. ignore_blank_key_values: ignore_blank_key_values,
  323. **embargo_values )
  324. provenance_log_event( attributes: attributes,
  325. current_user: current_user,
  326. event: EVENT_EMBARGO,
  327. event_note: event_note,
  328. ignore_blank_key_values: ignore_blank_key_values,
  329. prov_key_values: prov_key_values )
  330. end
  331. 1 def provenance_fixity_check( current_user:,
  332. event_note: '',
  333. fixity_check_status:,
  334. fixity_check_note:,
  335. **added_prov_key_values )
  336. event = EVENT_FIXITY_CHECK
  337. attributes, ignore_blank_key_values = attributes_for_provenance_fixity_check
  338. added_prov_key_values = { fixity_check_status: fixity_check_status,
  339. fixity_check_note: fixity_check_note }.merge added_prov_key_values
  340. event_note = fixity_check_status if event_note.blank?
  341. prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  342. current_user: current_user,
  343. event: event,
  344. event_note: event_note,
  345. ignore_blank_key_values: ignore_blank_key_values,
  346. **added_prov_key_values )
  347. provenance_log_event( attributes: nil,
  348. event: event,
  349. current_user: current_user,
  350. event_note: event_note,
  351. ignore_blank_key_values: false,
  352. prov_key_values: prov_key_values )
  353. end
  354. 1 def provenance_ingest( current_user:,
  355. event_note: '',
  356. calling_class:,
  357. ingest_id:,
  358. ingester:,
  359. ingest_timestamp:,
  360. **added_prov_key_values )
  361. event = EVENT_INGEST
  362. attributes, ignore_blank_key_values = attributes_for_provenance_ingest
  363. added_prov_key_values = { calling_class: calling_class,
  364. ingest_id: ingest_id,
  365. ingester: ingester,
  366. ingest_timestamp: ingest_timestamp }.merge added_prov_key_values
  367. prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  368. current_user: current_user,
  369. event: event,
  370. event_note: event_note,
  371. ignore_blank_key_values: ignore_blank_key_values,
  372. **added_prov_key_values )
  373. provenance_log_event( attributes: nil,
  374. event: event,
  375. current_user: current_user,
  376. event_note: event_note,
  377. ignore_blank_key_values: false,
  378. prov_key_values: prov_key_values )
  379. end
  380. 1 def provenance_log_for_event( attributes: [],
  381. current_user:,
  382. event:,
  383. event_note: '',
  384. ignore_blank_key_values: false,
  385. **prov_key_values )
  386. raise ProvenanceLogError( "Unknown provenance log event: #{event}" ) unless EVENTS.contains( event )
  387. provenance_log_event( attributes: attributes,
  388. current_user: current_user,
  389. event: event,
  390. event_note: event_note,
  391. ignore_blank_key_values: ignore_blank_key_values,
  392. prov_key_values: prov_key_values )
  393. end
  394. 1 def provenance_migrate( current_user:, event_note: '', migrate_direction:, parent_id: nil, **added_prov_key_values )
  395. event = EVENT_MIGRATE
  396. attributes, ignore_blank_key_values = attributes_for_provenance_migrate
  397. added_prov_key_values = if parent_id.present?
  398. { migrate_direction: migrate_direction, parent_id: parent_id }.merge added_prov_key_values
  399. else
  400. { migrate_direction: migrate_direction }.merge added_prov_key_values
  401. end
  402. event_note = migrate_direction if event_note.blank?
  403. prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  404. current_user: current_user,
  405. event: event,
  406. event_note: event_note,
  407. ignore_blank_key_values: ignore_blank_key_values,
  408. **added_prov_key_values )
  409. provenance_log_event( attributes: nil,
  410. event: event,
  411. current_user: current_user,
  412. event_note: event_note,
  413. ignore_blank_key_values: false,
  414. prov_key_values: prov_key_values )
  415. end
  416. 1 def provenance_mint_doi( current_user:, event_note: '' )
  417. 1 attributes, ignore_blank_key_values = attributes_for_provenance_mint_doi
  418. 1 provenance_log_event( attributes: attributes,
  419. current_user: current_user,
  420. event: EVENT_MINT_DOI,
  421. event_note: event_note,
  422. ignore_blank_key_values: ignore_blank_key_values )
  423. end
  424. 1 def provenance_publish( current_user:, event_note: '', message: '' )
  425. 1 attributes, ignore_blank_key_values = attributes_for_provenance_publish
  426. 1 prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  427. current_user: current_user,
  428. event: EVENT_PUBLISH,
  429. event_note: event_note,
  430. ignore_blank_key_values: ignore_blank_key_values,
  431. message: message )
  432. provenance_log_event( attributes: attributes,
  433. current_user: current_user,
  434. event: EVENT_PUBLISH,
  435. event_note: event_note,
  436. ignore_blank_key_values: ignore_blank_key_values,
  437. prov_key_values: prov_key_values )
  438. end
  439. 1 def provenance_tombstone( current_user:,
  440. event_note: '',
  441. epitaph:,
  442. depositor_at_tombstone:,
  443. visibility_at_tombstone: )
  444. attributes, ignore_blank_key_values = attributes_for_provenance_tombstone
  445. event = EVENT_TOMBSTONE
  446. prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  447. current_user: current_user,
  448. event: event,
  449. event_note: event_note,
  450. ignore_blank_key_values: false,
  451. epitaph: epitaph,
  452. depositor_at_tombstone: depositor_at_tombstone,
  453. visibility_at_tombstone: visibility_at_tombstone )
  454. provenance_log_event( attributes: attributes,
  455. current_user: current_user,
  456. event: event,
  457. event_note: event_note,
  458. ignore_blank_key_values: ignore_blank_key_values,
  459. prov_key_values: prov_key_values )
  460. end
  461. 1 def provenance_unembargo( current_user:, event_note: '', message: '', embargo_visibility:, embargo_visibility_after: )
  462. attributes, ignore_blank_key_values = attributes_for_provenance_embargo
  463. prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  464. current_user: current_user,
  465. event: EVENT_UNEMBARGO,
  466. event_note: event_note,
  467. ignore_blank_key_values: ignore_blank_key_values,
  468. message: message,
  469. embargo_visibility: embargo_visibility,
  470. embargo_visibility_after: embargo_visibility_after )
  471. provenance_log_event( attributes: attributes,
  472. current_user: current_user,
  473. event: EVENT_UNEMBARGO,
  474. event_note: event_note,
  475. ignore_blank_key_values: ignore_blank_key_values,
  476. prov_key_values: prov_key_values )
  477. end
  478. 1 def provenance_unpublish( current_user:, event_note: '' )
  479. 1 attributes, ignore_blank_key_values = attributes_for_provenance_unpublish
  480. 1 provenance_log_event( attributes: attributes,
  481. current_user: current_user,
  482. event: EVENT_UNPUBLISH,
  483. event_note: event_note,
  484. ignore_blank_key_values: ignore_blank_key_values )
  485. end
  486. 1 def provenance_update( current_user:, event_note: '', **added_prov_key_values )
  487. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  488. # ::Deepblue::LoggingHelper.called_from,
  489. # "added_prov_key_values=#{added_prov_key_values}",
  490. # "" ]
  491. 1 attributes, ignore_blank_key_values = attributes_for_provenance_update
  492. 1 event = EVENT_UPDATE
  493. 1 prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  494. current_user: current_user,
  495. event: event,
  496. event_note: event_note,
  497. ignore_blank_key_values: ignore_blank_key_values,
  498. **added_prov_key_values )
  499. 1 provenance_log_event( attributes: attributes,
  500. current_user: current_user,
  501. event: event,
  502. event_note: event_note,
  503. ignore_blank_key_values: ignore_blank_key_values,
  504. prov_key_values: prov_key_values )
  505. end
  506. 1 def provenance_update_embargo_key_values( update_attr_key_values: )
  507. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  508. # ::Deepblue::LoggingHelper.called_from,
  509. # "update_attr_key_values=#{update_attr_key_values}",
  510. # "" ]
  511. 1 return nil unless update_attr_key_values.present?
  512. 1 return nil unless update_attr_key_values.key? :embargo
  513. embargo_key_values = update_attr_key_values[:embargo]
  514. update_attr_key_values.delete :embargo
  515. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  516. # ::Deepblue::LoggingHelper.called_from,
  517. # "update_attr_key_values=#{update_attr_key_values}",
  518. # "embargo_key_values=#{embargo_key_values}",
  519. # "" ]
  520. embargo_key_values
  521. end
  522. 1 def update_attribute_changed?( update_attr: )
  523. old_value = update_attr[:old_value]
  524. new_value = update_attr[:new_value]
  525. old_value != new_value
  526. end
  527. 1 def provenance_log_update_after( current_user:, event_note: '', update_attr_key_values: nil )
  528. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  529. # ::Deepblue::LoggingHelper.called_from,
  530. # "update_attr_key_values=#{update_attr_key_values}",
  531. # "" ]
  532. 1 embargo_key_values = provenance_update_embargo_key_values( update_attr_key_values: update_attr_key_values )
  533. 1 update_attr_key_values = ProvenanceHelper.update_attribute_key_values( curation_concern: for_provenance_object,
  534. **update_attr_key_values )
  535. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  536. # ::Deepblue::LoggingHelper.called_from,
  537. # "update_attr_key_values=#{update_attr_key_values}",
  538. # "" ]
  539. 1 if update_attr_key_values.present? || embargo_key_values.present?
  540. 1 if embargo_key_values.present?
  541. embargo_key_values.each_pair do |key, value|
  542. update_attr_key_values[key] = value if update_attribute_changed?( update_attr: value )
  543. end
  544. end
  545. 1 provenance_update( current_user: current_user, event_note: event_note, **update_attr_key_values )
  546. provenance_embargo( current_user: current_user,
  547. event_note: event_note,
  548. 1 embargo_key_values: embargo_key_values ) if embargo_key_values.present?
  549. end
  550. end
  551. 1 def provenance_log_update_before( form_params: )
  552. # LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  553. # Deepblue::LoggingHelper.called_from,
  554. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  555. # ActiveSupport::JSON.encode( form_params ),
  556. # 'form_params:',
  557. # form_params ]
  558. 1 update_attr_key_values = ProvenanceHelper.form_params_to_update_attribute_key_values( curation_concern: for_provenance_object,
  559. form_params: form_params )
  560. # LoggingHelper.bold_debug [ "provenance_log_update_before", 'update_attr_key_values:', update_attr_key_values ]
  561. 1 update_attr_key_values
  562. end
  563. 1 def provenance_update_version( current_user:,
  564. event_note: '',
  565. new_create_date:,
  566. new_revision_id:,
  567. prior_create_date:,
  568. prior_revision_id:,
  569. revision_id:,
  570. **added_prov_key_values )
  571. attributes, ignore_blank_key_values = attributes_for_provenance_update_version
  572. event = EVENT_UPDATE_VERSION
  573. added_prov_key_values = { new_create_date: new_create_date,
  574. new_revision_id: new_revision_id,
  575. prior_create_date: prior_create_date,
  576. prior_revision_id: prior_revision_id,
  577. revision_id: revision_id }.merge added_prov_key_values
  578. prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  579. current_user: current_user,
  580. event: event,
  581. event_note: event_note,
  582. ignore_blank_key_values: ignore_blank_key_values,
  583. **added_prov_key_values )
  584. provenance_log_event( attributes: attributes,
  585. current_user: current_user,
  586. event: event,
  587. event_note: event_note,
  588. ignore_blank_key_values: ignore_blank_key_values,
  589. prov_key_values: prov_key_values )
  590. end
  591. 1 def provenance_upload( current_user:, event_note: '' )
  592. provenance_log_event( attributes: attributes_for_provenance_upload,
  593. current_user: current_user,
  594. event: EVENT_UPLOAD,
  595. event_note: event_note,
  596. ignore_blank_key_values: true )
  597. end
  598. 1 def provenance_virus_scan( current_user: nil,
  599. event_note: '',
  600. scan_result:,
  601. **added_prov_key_values )
  602. event = EVENT_VIRUS_SCAN
  603. attributes, ignore_blank_key_values = attributes_for_provenance_virus_scan
  604. added_prov_key_values = { scan_result: scan_result }.merge added_prov_key_values
  605. event_note = scan_result if event_note.blank?
  606. prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  607. current_user: current_user,
  608. event: event,
  609. event_note: event_note,
  610. ignore_blank_key_values: ignore_blank_key_values,
  611. **added_prov_key_values )
  612. provenance_log_event( attributes: nil,
  613. event: event,
  614. current_user: current_user,
  615. event_note: event_note,
  616. ignore_blank_key_values: false,
  617. prov_key_values: prov_key_values )
  618. end
  619. 1 def provenance_workflow( current_user: nil,
  620. event_note: '',
  621. workflow_name:,
  622. workflow_state_prior:,
  623. workflow_state:,
  624. **added_prov_key_values )
  625. event = EVENT_WORKFLOW
  626. attributes, ignore_blank_key_values = attributes_for_provenance_workflow
  627. added_prov_key_values = { workflow_name: workflow_name,
  628. workflow_state_prior: workflow_state_prior,
  629. workflow_state: workflow_state }.merge added_prov_key_values
  630. event_note = workflow_state if event_note.blank?
  631. prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  632. current_user: current_user,
  633. event: event,
  634. event_note: event_note,
  635. ignore_blank_key_values: ignore_blank_key_values,
  636. **added_prov_key_values )
  637. provenance_log_event( attributes: nil,
  638. event: event,
  639. current_user: current_user,
  640. event_note: event_note,
  641. ignore_blank_key_values: false,
  642. prov_key_values: prov_key_values )
  643. end
  644. 1 protected
  645. 1 def provenance_log_event( attributes:,
  646. current_user:,
  647. event:,
  648. event_note:,
  649. ignore_blank_key_values:,
  650. id: for_provenance_id,
  651. prov_key_values: nil )
  652. 3 if prov_key_values.blank?
  653. 2 prov_key_values = provenance_attribute_values_for_snapshot( attributes: attributes,
  654. current_user: current_user,
  655. event: event,
  656. event_note: event_note,
  657. ignore_blank_key_values: ignore_blank_key_values )
  658. end
  659. 1 class_name = for_provenance_class.name
  660. 1 for_provenance_event_cache_write( event: event, id: id )
  661. 1 ProvenanceHelper.log( class_name: class_name, id: id, event: event, event_note: event_note, **prov_key_values )
  662. end
  663. end
  664. end
  665. 1 module ActiveFedora
  666. 1 module PersistenceExt
  667. 1 def self.prepended( base )
  668. base.singleton_class.prepend( ClassMethods )
  669. end
  670. 1 module ClassMethods
  671. # def update( attributes )
  672. # Rails.logger.debug "ActiveFedora::Persistence.update(#{ActiveSupport::JSON.encode attributes})"
  673. # if respond_to? :provenance_attribute_values_before_update
  674. # provenance_attribute_values_before_update = provenance_attribute_values_for_update( current_user: '' )
  675. # Rails.logger.debug ">>>>>>"
  676. # Rails.logger.debug "provenance_log_update_before"
  677. # Rails.logger.debug "provenance_attribute_values_before_update=#{ActiveSupport::JSON.encode provenance_attribute_values_before_update}"
  678. # Rails.logger.debug ">>>>>>"
  679. # end
  680. #
  681. # rv = super( attributes )
  682. #
  683. # if respond_to? :provenance_attribute_values_before_update
  684. # Rails.logger.debug ">>>>>>"
  685. # Rails.logger.debug "provenance_log_update_after"
  686. # Rails.logger.debug "provenance_attribute_values_before_update=#{ActiveSupport::JSON.encode provenance_attribute_values_before_update}"
  687. # Rails.logger.debug ">>>>>>"
  688. # provenance_update( current_user: '',
  689. # provenance_attribute_values_before_update: provenance_attribute_values_before_update )
  690. # end
  691. # rv
  692. # end
  693. end
  694. # def to_pretty_json
  695. # JSON.pretty_generate(self)
  696. # end
  697. end
  698. end

app/models/concerns/deepblue/workflow_event_behavior.rb

31.25% lines covered

32 relevant lines. 10 lines covered and 22 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. # class WorkflowEventError < AbstractEventError
  4. # end
  5. 1 module WorkflowEventBehavior
  6. 1 def workflow_create( current_user:, event_note: "" )
  7. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  8. Deepblue::LoggingHelper.called_from,
  9. Deepblue::LoggingHelper.obj_class( 'class', self ),
  10. "current_user=#{current_user}",
  11. "event_note=#{event_note}",
  12. "" ]
  13. provenance_create( current_user: current_user, event_note: event_note )
  14. email_rds_create( current_user: current_user, event_note: event_note )
  15. # parameters = email_rds_create( current_user: current_user, event_note: event_note, return_email_parameters: true )
  16. # summary = "#{parameters[:subject]} - #{parameters[:id]}"
  17. # jira_url = JiraHelper.new_ticket( summary: summary, description: parameters[ :body ] )
  18. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  19. # Deepblue::LoggingHelper.called_from,
  20. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  21. # "jira_url=#{jira_url}",
  22. # "" ]
  23. # return if jira_url.nil?
  24. JiraNewTicketJob.perform_later( work_id: id, current_user: current_user )
  25. end
  26. 1 def workflow_embargo( current_user:, event_note: "" )
  27. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  28. Deepblue::LoggingHelper.called_from,
  29. Deepblue::LoggingHelper.obj_class( 'class', self ),
  30. "current_user=#{current_user}",
  31. "event_note=#{event_note}",
  32. "" ]
  33. provenance_embargo( current_user: current_user, event_note: event_note )
  34. end
  35. 1 def workflow_destroy( current_user:, event_note: "" )
  36. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  37. Deepblue::LoggingHelper.called_from,
  38. Deepblue::LoggingHelper.obj_class( 'class', self ),
  39. "current_user=#{current_user}",
  40. "event_note=#{event_note}",
  41. "" ]
  42. provenance_destroy( current_user: current_user, event_note: event_note )
  43. email_rds_destroy( current_user: current_user, event_note: event_note )
  44. end
  45. 1 def workflow_publish( current_user:, event_note: "", message: "" )
  46. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  47. Deepblue::LoggingHelper.called_from,
  48. Deepblue::LoggingHelper.obj_class( 'class', self ),
  49. "current_user=#{current_user}",
  50. "event_note=#{event_note}",
  51. "message=#{message}",
  52. "" ]
  53. if respond_to? :date_published
  54. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  55. # Deepblue::LoggingHelper.called_from,
  56. # "self.date_modified=#{self.date_modified}",
  57. # "self.date_published=#{self.date_published}",
  58. # "" ]
  59. self.date_published = Hyrax::TimeService.time_in_utc
  60. self.date_modified = DateTime.now
  61. self.save!
  62. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  63. # Deepblue::LoggingHelper.called_from,
  64. # "self.date_modified=#{self.date_modified}",
  65. # "self.date_published=#{self.date_published}",
  66. # "" ]
  67. else
  68. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  69. Deepblue::LoggingHelper.called_from,
  70. "does not respond to :date_published",
  71. "" ]
  72. end
  73. provenance_publish( current_user: current_user, event_note: event_note, message: message )
  74. email_rds_publish( current_user: current_user, event_note: event_note, message: message )
  75. end
  76. 1 def workflow_unembargo( current_user:, event_note: "" )
  77. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  78. Deepblue::LoggingHelper.called_from,
  79. Deepblue::LoggingHelper.obj_class( 'class', self ),
  80. "current_user=#{current_user}",
  81. "event_note=#{event_note}",
  82. "" ]
  83. provenance_embargo( current_user: current_user, event_note: event_note )
  84. end
  85. 1 def workflow_unpublish( current_user:, event_note: "" )
  86. ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  87. Deepblue::LoggingHelper.called_from,
  88. Deepblue::LoggingHelper.obj_class( 'class', self ),
  89. "current_user=#{current_user}",
  90. "event_note=#{event_note}",
  91. "" ]
  92. provenance_unpublish( current_user: current_user, event_note: event_note )
  93. email_rds_unpublish( current_user: current_user, event_note: event_note )
  94. end
  95. 1 def workflow_update_before( current_user:, event_note: "" )
  96. end
  97. 1 def workflow_update_after( current_user:, event_note: "" )
  98. end
  99. end
  100. end

app/models/concerns/hyrax/collection_behavior.rb

58.82% lines covered

17 relevant lines. 10 lines covered and 7 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require File.join( Gem::Specification.find_by_name("hyrax").full_gem_path, "app/models/concerns/hyrax/collection_behavior.rb" )
  3. 1 module Hyrax
  4. # monkey patch Hyrax::CollectionBehavior
  5. # monkey patch methods that don't specify row count to return from search_with_conditions.
  6. # The default value for row count leads to errors for works with large numbers of files.
  7. 1 module CollectionBehavior
  8. 1 include ::Deepblue::WorkflowEventBehavior
  9. # Compute the sum of each file in the collection using Solr to
  10. # avoid having to access Fedora
  11. #
  12. # @return [Fixnum] size of collection in bytes
  13. # @raise [RuntimeError] unsaved record does not exist in solr
  14. 1 def bytes
  15. 21 return 0 if member_object_ids.empty?
  16. raise "Collection must be saved to query for bytes" if new_record?
  17. # One query per member_id because Solr is not a relational database
  18. member_object_ids.collect { |work_id| size_for_work(work_id) }.sum
  19. end
  20. # Use this query to get the ids of the member objects (since the containment
  21. # association has been flipped)
  22. 1 def member_object_ids
  23. 21 return [] unless id
  24. ActiveFedora::Base.search_with_conditions("member_of_collection_ids_ssim:#{id}", rows: 1000 ).map(&:id)
  25. end
  26. # Calculate the size of all the files in the work
  27. # @param work_id [String] identifer for a work
  28. # @return [Integer] the size in bytes
  29. 1 def size_for_work(work_id)
  30. argz = { fl: "id, #{file_size_field}",
  31. fq: "{!join from=#{member_ids_field} to=id}id:#{work_id}",
  32. rows: 10_000 }
  33. files = ::FileSet.search_with_conditions({}, argz)
  34. files.reduce(0) { |sum, f| sum + f[file_size_field].to_i }
  35. end
  36. # Field name to look up when locating the size of each file in Solr.
  37. # Override for your own installation if using something different
  38. 1 def file_size_field
  39. Solrizer.solr_name(:file_size, Hyrax::FileSetIndexer::STORED_LONG)
  40. end
  41. end
  42. end

app/models/concerns/hyrax/uploaded_file.rb

100.0% lines covered

8 relevant lines. 8 lines covered and 0 lines missed.
    
  1. 1 module Hyrax
  2. # Store a file uploaded by a user. Eventually these files get
  3. # attached to FileSets and pushed into Fedora.
  4. 1 class UploadedFile < ActiveRecord::Base
  5. 1 self.table_name = 'uploaded_files'
  6. 1 mount_uploader :file, UploadedFileUploader
  7. 1 alias uploader file
  8. 1 has_many :job_io_wrappers,
  9. inverse_of: 'uploaded_file',
  10. class_name: 'JobIoWrapper',
  11. dependent: :destroy
  12. 1 belongs_to :user, class_name: '::User'
  13. 1 before_destroy :remove_file!
  14. end
  15. end

app/models/concerns/umrdr/solr_document_behavior.rb

48.44% lines covered

64 relevant lines. 31 lines covered and 33 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Umrdr
  3. 1 module SolrDocumentBehavior
  4. 1 extend ActiveSupport::Concern
  5. 1 def access_deepblue
  6. fetch(Solrizer.solr_name('access_deepblue'), [])
  7. end
  8. 1 def authoremail
  9. Array(self[Solrizer.solr_name('authoremail')]).first
  10. end
  11. 1 def curation_notes_admin
  12. fetch(Solrizer.solr_name('curation_notes_admin'), [])
  13. end
  14. 1 def curation_notes_user
  15. fetch(Solrizer.solr_name('curation_notes_user'), [])
  16. end
  17. 1 def date_coverage
  18. Array(self[Solrizer.solr_name('date_coverage')]).first
  19. end
  20. 1 def date_published
  21. date_published2
  22. end
  23. 1 def date_published2
  24. self[ 'date_published_dtsim' ]
  25. end
  26. ## begin DOI methods
  27. 1 def doi
  28. rv = doi_the_correct_one
  29. # rv = Array( self[ Solrizer.solr_name( 'doi', :symbol ) ] ).first
  30. # rv = self[ Solrizer.solr_name( 'doi', :symbol ) ]
  31. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  32. # Deepblue::LoggingHelper.called_from,
  33. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  34. # "doi = #{doi}",
  35. # "" ]
  36. return rv
  37. end
  38. 1 def doi_the_correct_one
  39. # rv = Array( self[Solrizer.solr_name('doi')] ).first
  40. rv = self[ Solrizer.solr_name( 'doi', :symbol ) ]
  41. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  42. # Deepblue::LoggingHelper.called_from,
  43. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  44. # "doi = #{doi}",
  45. # "" ]
  46. return rv
  47. end
  48. 1 def doi_minted?
  49. # the first time this is called, doi will not be in solr.
  50. # @solr_document[ Solrizer.solr_name( 'doi', :symbol ) ].first
  51. doi_the_correct_one.present?
  52. rescue
  53. nil
  54. end
  55. 1 def doi_minting_enabled?
  56. ::Deepblue::DoiBehavior::DOI_MINTING_ENABLED
  57. end
  58. 1 def doi_pending?
  59. #@solr_document[ Solrizer.solr_name( 'doi', :symbol ) ].first == ::Deepblue::DoiBehavior::DOI_PENDING
  60. doi_the_correct_one == ::Deepblue::DoiBehavior::DOI_PENDING
  61. end
  62. ## end DOI methods
  63. 1 def file_size
  64. Array(self['file_size_lts']).first # standard lookup Solrizer.solr_name('file_size')] produces solr_document['file_size_tesim']
  65. end
  66. 1 def file_size_human_readable
  67. size = file_size
  68. ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert( size, precision: 3 )
  69. end
  70. 1 def fundedby
  71. fetch(Solrizer.solr_name('fundedby'), [])
  72. end
  73. 1 def fundedby_other
  74. Array(self[Solrizer.solr_name('fundedby_other')]).first
  75. end
  76. 1 def grantnumber
  77. Array(self[Solrizer.solr_name('grantnumber')]).first
  78. end
  79. 1 def methodology
  80. Array(self[Solrizer.solr_name('methodology')]).first
  81. end
  82. 1 def original_checksum
  83. Array(self[Solrizer.solr_name('original_checksum')]).first
  84. end
  85. 1 def referenced_by
  86. # Array(self[Solrizer.solr_name('referenced_by')]).first
  87. fetch(Solrizer.solr_name('referenced_by'), [])
  88. end
  89. 1 def rights_license_other
  90. Array(self[Solrizer.solr_name('rights_license_other')]).first
  91. end
  92. 1 def subject_discipline
  93. fetch(Solrizer.solr_name('subject_discipline'), [])
  94. end
  95. 1 def tombstone
  96. Array(self[Solrizer.solr_name('tombstone')]).first
  97. end
  98. 1 def total_file_size
  99. Array(self['total_file_size_lts']).first # standard lookup Solrizer.solr_name('total_file_size')] produces solr_document['file_size_tesim']
  100. end
  101. 1 def total_file_size_human_readable
  102. total = total_file_size
  103. ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert( total, precision: 3 )
  104. end
  105. 1 def virus_scan_service
  106. Array(self[Solrizer.solr_name('virus_scan_service')]).first
  107. end
  108. 1 def virus_scan_status
  109. Array(self[Solrizer.solr_name('virus_scan_status')]).first
  110. end
  111. 1 def virus_scan_status_date
  112. Array(self[Solrizer.solr_name('virus_scan_status_date')]).first
  113. end
  114. end
  115. end

app/models/concerns/umrdr/umrdr_work_behavior.rb

40.0% lines covered

45 relevant lines. 18 lines covered and 27 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Umrdr
  3. 1 module UmrdrWorkBehavior
  4. 1 extend ActiveSupport::Concern
  5. # Calculate the size of all the files in the work
  6. # @return [Integer] the size in bytes
  7. 1 def size_of_work
  8. work_id = id
  9. file_size_field = Solrizer.solr_name(:file_size, Hyrax::FileSetIndexer::STORED_LONG)
  10. member_ids_field = Solrizer.solr_name('member_ids', :symbol)
  11. argz = { fl: "id, #{file_size_field}",
  12. fq: "{!join from=#{member_ids_field} to=id}id:#{work_id}",
  13. rows: 10_000 }
  14. files = ::FileSet.search_with_conditions({}, argz)
  15. files.reduce(0) { |sum, f| sum + f[file_size_field].to_i }
  16. end
  17. 1 def total_file_size_add_file_set( _file_set )
  18. # size = file_size_from_file_set file_set
  19. # total_file_size_add size
  20. update_total_file_size
  21. end
  22. 1 def total_file_size_add_file_set!( _file_set )
  23. # size = file_size_from_file_set file_set
  24. # total_file_size_add! size
  25. update_total_file_size!
  26. end
  27. 1 def total_file_size_human_readable
  28. 1 total = total_file_size
  29. 1 ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert( total, precision: 3 )
  30. end
  31. 1 def total_file_size_subtract_file_set( _file_set )
  32. # size = file_size_from_file_set file_set
  33. # total_file_size_add( -size )
  34. update_total_file_size
  35. end
  36. 1 def total_file_size_subtract_file_set!( _file_set )
  37. # size = file_size_from_file_set file_set
  38. # total_file_size_add!( -size )
  39. update_total_file_size!
  40. end
  41. 1 def update_total_file_size
  42. # total = 0
  43. # file_sets.each do |fs|
  44. # file_size = file_size_from_file_set fs
  45. # total += file_size
  46. # end
  47. total = size_of_work
  48. self.total_file_size = total
  49. # total_file_size_human_readable = ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert( total, precision: 3 )
  50. end
  51. 1 def update_total_file_size!
  52. update_total_file_size
  53. save!
  54. end
  55. 1 private
  56. 1 def file_size_from_file_set( file_set )
  57. return 0 if file_set.nil?
  58. # return 0 if file_set.file_size.blank?
  59. # file_set.file_size[0].to_i
  60. file_set.file_size_value
  61. end
  62. 1 def total_file_size_add( file_size )
  63. current_total_size = total_file_size
  64. current_total_size = ( current_total_size.nil? ? 0 : current_total_size ) + file_size
  65. current_total_size = 0 if current_total_size.negative?
  66. self.total_file_size = current_total_size
  67. end
  68. 1 def total_file_size_add!( file_size )
  69. if 1 == file_sets.size
  70. total_file_size_set file_size
  71. save!
  72. elsif 0 != file_size
  73. total_file_size_add file_size
  74. save!
  75. end
  76. end
  77. 1 def total_file_size_set( file_size )
  78. self.total_file_size = file_size
  79. end
  80. end
  81. end

app/models/concerns/umrdr/umrdr_work_metadata.rb

100.0% lines covered

78 relevant lines. 78 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Umrdr
  3. 1 module UmrdrWorkMetadata
  4. 1 extend ActiveSupport::Concern
  5. 1 included do
  6. 2 property :access_deepblue, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#access_deepblue'), multiple: true do |index|
  7. 4 index.type :text
  8. 4 index.as :stored_searchable
  9. end
  10. 2 property :access_deepblue_ordered, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#access_deepblue_ordered'), multiple: false do |index|
  11. 4 index.type :text
  12. 4 index.as :stored_searchable
  13. end
  14. 2 property :authoremail, predicate: ::RDF::Vocab::FOAF.mbox, multiple: false do |index|
  15. 4 index.type :text
  16. 4 index.as :stored_searchable
  17. end
  18. 2 property :creator_ordered, predicate: ::RDF::Vocab::MODS.name, multiple: false do |index|
  19. 4 index.type :text
  20. 4 index.as :stored_searchable
  21. end
  22. 2 property :curation_notes_admin, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#curation_notes_admin'), multiple: true do |index|
  23. 4 index.type :text
  24. 4 index.as :stored_searchable
  25. end
  26. 2 property :curation_notes_admin_ordered, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#curation_notes_admin_ordered'), multiple: false do |index|
  27. 4 index.type :text
  28. 4 index.as :stored_searchable
  29. end
  30. 2 property :curation_notes_user, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#curation_notes_user'), multiple: true do |index|
  31. 4 index.type :text
  32. 4 index.as :stored_searchable
  33. end
  34. 2 property :curation_notes_user_ordered, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#curation_notes_user_ordered'), multiple: false do |index|
  35. 4 index.type :text
  36. 4 index.as :stored_searchable
  37. end
  38. 2 property :date_coverage, predicate: ::RDF::Vocab::DC.temporal, multiple: false do |index|
  39. 4 index.type :text
  40. 4 index.as :stored_searchable, :facetable
  41. end
  42. 2 property :date_published, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#date_published'), multiple: false do |index|
  43. 4 index.type :text
  44. 4 index.as :stored_searchable, :facetable
  45. end
  46. 2 property :description_ordered, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#description_ordered'), multiple: false do |index|
  47. 4 index.type :text
  48. 4 index.as :stored_searchable
  49. end
  50. 2 property :doi, predicate: ::RDF::Vocab::Identifiers.doi, multiple: false do |index|
  51. 4 index.type :text
  52. 4 index.as :stored_searchable
  53. end
  54. 2 property :fundedby, predicate: ::RDF::Vocab::DISCO.fundedBy, multiple: true do |index|
  55. 4 index.type :text
  56. 4 index.as :stored_searchable
  57. end
  58. 2 property :fundedby_other, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#fundedby_other'), multiple: true do |index|
  59. 4 index.type :text
  60. 4 index.as :stored_searchable
  61. end
  62. 2 property :grantnumber, predicate: ::RDF::URI.new('http://purl.org/cerif/frapo/hasGrantNumber'), multiple: false do |index|
  63. 4 index.type :text
  64. 4 index.as :stored_searchable
  65. end
  66. 2 property :hdl, predicate: ::RDF::Vocab::Identifiers.hdl, multiple: false
  67. 2 property :referenced_by, predicate: ::RDF::Vocab::DC.isReferencedBy, multiple: true do |index|
  68. 4 index.type :text
  69. 4 index.as :stored_searchable
  70. end
  71. 2 property :referenced_by_ordered, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#referenced_by_ordered'), multiple: false do |index|
  72. 4 index.type :text
  73. 4 index.as :stored_searchable
  74. end
  75. 2 property :rights_license_other, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#rights_license_other'), multiple: false do |index|
  76. 4 index.type :text
  77. 4 index.as :stored_searchable
  78. end
  79. 2 property :keyword_ordered, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#keyword_ordered'), multiple: false do |index|
  80. 4 index.type :text
  81. 4 index.as :stored_searchable
  82. end
  83. 2 property :language_ordered, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#language_ordered'), multiple: false do |index|
  84. 4 index.type :text
  85. 4 index.as :stored_searchable
  86. end
  87. 2 property :methodology, predicate: ::RDF::URI.new('http://www.ddialliance.org/Specification/DDI-Lifecycle/3.2/XMLSchema/FieldLevelDocumentation/schemas/datacollection_xsd/elements/DataCollectionMethodology.html'), multiple: false do |index|
  88. 4 index.type :text
  89. 4 index.as :stored_searchable
  90. end
  91. 2 property :subject_discipline, predicate: ::RDF::Vocab::MODS.subject, multiple: true do |index|
  92. 4 index.type :text
  93. 4 index.as :stored_searchable, :facetable
  94. end
  95. 2 property :title_ordered, predicate: ::RDF::URI.new('https://deepblue.lib.umich.edu/data/help.help#title_ordered'), multiple: false do |index|
  96. 4 index.type :text
  97. 4 index.as :stored_searchable
  98. end
  99. 2 property :tombstone, predicate: ::RDF::Vocab::DC.provenance, multiple: true do |index|
  100. 4 index.type :text
  101. 4 index.as :stored_searchable
  102. end
  103. 2 property :total_file_size, predicate: ::RDF::Vocab::DC.SizeOrDuration, multiple: false
  104. # TODO: can't use the same predicate twice
  105. # property :total_file_size_human_readable, predicate: ::RDF::Vocab::DC.SizeOrDuration, multiple: false
  106. end
  107. end
  108. end

app/models/data_set.rb

64.52% lines covered

217 relevant lines. 140 lines covered and 77 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class DataSet < ActiveFedora::Base
  3. 1 include ::Hyrax::WorkBehavior
  4. 1 self.indexer = DataSetIndexer
  5. # Change this to restrict which works can be added as a child.
  6. # self.valid_child_concerns = []
  7. # self.human_readable_type = 'Data Set' # deprecated
  8. 1 include Umrdr::UmrdrWorkBehavior
  9. 1 include Umrdr::UmrdrWorkMetadata
  10. 1 include ::Deepblue::EmbargoableBehavior
  11. 1 validates :authoremail, presence: { message: 'You must have author contact information.' }
  12. 1 validates :creator, presence: { message: 'Your work must have a creator.' }
  13. 1 validates :description, presence: { message: 'Your work must have a description.' }
  14. 1 validates :methodology, presence: { message: 'Your work must have a description of the method for collecting the dataset.' }
  15. 1 validates :rights_license, presence: { message: 'You must select a license for your work.' }
  16. 1 validates :title, presence: { message: 'Your work must have a title.' }
  17. # This must be included at the end, because it finalizes the metadata
  18. # schema (by adding accepts_nested_attributes)
  19. 1 include ::Deepblue::DefaultMetadata
  20. 1 include ::Deepblue::MetadataBehavior
  21. 1 include ::Deepblue::EmailBehavior
  22. 1 include ::Deepblue::ProvenanceBehavior
  23. 1 include ::Deepblue::DoiBehavior
  24. 1 include ::Deepblue::WorkflowEventBehavior
  25. 1 after_initialize :set_defaults
  26. 1 before_destroy :provenance_before_destroy_data_set
  27. 1 def provenance_before_destroy_data_set
  28. # workflow_destroy does this
  29. # provenance_destroy( current_user: '' ) # , event_note: 'provenance_before_destroy_data_set' )
  30. end
  31. 1 def set_defaults
  32. 48 return unless new_record?
  33. 48 self.resource_type = ["Dataset"]
  34. end
  35. 1 def metadata_keys_all
  36. 7 %i[
  37. access_deepblue
  38. admin_set_id
  39. authoremail
  40. creator
  41. curation_notes_admin
  42. curation_notes_user
  43. date_coverage
  44. date_created
  45. date_modified
  46. date_published
  47. date_updated
  48. depositor
  49. description
  50. doi
  51. file_set_ids
  52. fundedby
  53. fundedby_other
  54. grantnumber
  55. keyword
  56. language
  57. location
  58. methodology
  59. prior_identifier
  60. referenced_by
  61. rights_license
  62. rights_license_other
  63. subject_discipline
  64. title
  65. tombstone
  66. total_file_count
  67. total_file_size
  68. total_file_size_human_readable
  69. visibility
  70. ]
  71. end
  72. # Title
  73. # Creator
  74. # Contact information
  75. # Discipline
  76. # Record URL
  77. 1 def metadata_keys_email_standard
  78. %i[
  79. title
  80. creator
  81. depositor
  82. authoremail
  83. description
  84. subject_discipline
  85. location
  86. ]
  87. end
  88. 1 def metadata_keys_brief
  89. 1 %i[
  90. authoremail
  91. title
  92. visibility
  93. ]
  94. end
  95. 1 def metadata_keys_report
  96. %i[
  97. access_deepblue
  98. authoremail
  99. creator
  100. curation_notes_user
  101. date_coverage
  102. date_published
  103. depositor
  104. description
  105. doi
  106. fundedby
  107. fundedby_other
  108. grantnumber
  109. keyword
  110. language
  111. methodology
  112. referenced_by
  113. rights_license
  114. rights_license_other
  115. subject_discipline
  116. title
  117. total_file_count
  118. total_file_size_human_readable
  119. ]
  120. end
  121. 1 def metadata_keys_update
  122. 3 %i[
  123. authoremail
  124. title
  125. visibility
  126. ]
  127. end
  128. 1 def attributes_all_for_email
  129. metadata_keys_all
  130. end
  131. 1 def attributes_all_for_provenance
  132. 7 metadata_keys_all
  133. end
  134. 1 def attributes_brief_for_email
  135. metadata_keys_brief
  136. end
  137. 1 def attributes_brief_for_provenance
  138. 1 metadata_keys_brief
  139. end
  140. 1 def attributes_for_email_rds_create
  141. attributes = %i[ title location creator depositor authoremail subject_discipline id type ]
  142. return attributes, Deepblue::AbstractEventBehavior::USE_BLANK_KEY_VALUES
  143. end
  144. 1 def attributes_standard_for_email
  145. metadata_keys_email_standard
  146. end
  147. 1 def attributes_update_for_email
  148. metadata_keys_update
  149. end
  150. 1 def attributes_update_for_provenance
  151. 3 metadata_keys_update
  152. end
  153. 1 def for_email_route
  154. for_event_route
  155. end
  156. 1 def for_event_route
  157. Rails.application.routes.url_helpers.hyrax_data_set_path( id: self.id ) # rubocop:disable Style/RedundantSelf
  158. end
  159. 1 def for_provenance_route
  160. for_event_route
  161. end
  162. 1 def human_readable_type
  163. 'Work'
  164. end
  165. 1 def title_type
  166. 'Data Set'
  167. end
  168. 1 def map_email_attributes_override!( event:, # rubocop:disable Lint/UnusedMethodArgument
  169. attribute:,
  170. ignore_blank_key_values:,
  171. email_key_values: )
  172. value = nil
  173. handled = case attribute.to_s
  174. when 'data_set_url'
  175. value = data_set_url
  176. true
  177. when 'location'
  178. value = data_set_url
  179. true
  180. when 'file_set_ids'
  181. value = file_set_ids
  182. true
  183. when 'total_file_count'
  184. value = total_file_count
  185. true
  186. when 'total_file_size_human_readable'
  187. value = total_file_size_human_readable
  188. true
  189. when 'visibility'
  190. value = visibility
  191. true
  192. when 'work_or_collection'
  193. value = "Work"
  194. true
  195. when 'type'
  196. value = "Work"
  197. true
  198. else
  199. false
  200. end
  201. return false unless handled
  202. if ignore_blank_key_values
  203. email_key_values[attribute] = value if value.present?
  204. else
  205. email_key_values[attribute] = value
  206. end
  207. return true
  208. end
  209. 1 def data_set_url
  210. Deepblue::EmailHelper.data_set_url( data_set: self )
  211. rescue Exception => e # rubocop:disable Lint/RescueException
  212. Rails.logger.error "#{e.class} #{e.message} at #{e.backtrace[0]}"
  213. return e.to_s
  214. end
  215. 1 def workflow_state
  216. wgid = to_global_id.to_s
  217. entity = Sipity::Entity.where( proxy_for_global_id: wgid )&.first
  218. entity&.workflow_state_name
  219. end
  220. 1 def map_provenance_attributes_override!( event:, # rubocop:disable Lint/UnusedMethodArgument
  221. attribute:,
  222. ignore_blank_key_values:,
  223. prov_key_values: )
  224. 51 value = nil
  225. 51 handled = case attribute.to_s
  226. when 'file_set_ids'
  227. 4 value = file_set_ids
  228. true
  229. when 'total_file_count'
  230. value = total_file_count
  231. true
  232. when 'total_file_size_human_readable'
  233. value = total_file_size_human_readable
  234. true
  235. when 'visibility'
  236. 2 value = visibility
  237. 2 true
  238. else
  239. 45 false
  240. end
  241. 47 return false unless handled
  242. 2 if ignore_blank_key_values
  243. 1 prov_key_values[attribute] = value if value.present?
  244. else
  245. 1 prov_key_values[attribute] = value
  246. end
  247. 2 return true
  248. end
  249. 1 def metadata_hash_override( key:, ignore_blank_values:, key_values: )
  250. 4 value = nil
  251. 4 handled = case key.to_s
  252. when 'file_set_ids'
  253. 1 value = file_set_ids
  254. true
  255. when 'total_file_count'
  256. value = total_file_count
  257. true
  258. when 'total_file_size'
  259. 1 value = total_file_size
  260. 1 true
  261. when 'total_file_size_human_readable'
  262. 1 value = total_file_size_human_readable
  263. 1 true
  264. # when 'visibility'
  265. # value = visibility
  266. # true
  267. else
  268. 1 false
  269. end
  270. 3 return false unless handled
  271. 2 if ignore_blank_values
  272. key_values[key] = value if value.present?
  273. else
  274. 2 key_values[key] = value
  275. end
  276. 2 return true
  277. end
  278. 1 def metadata_report_contained_objects
  279. file_sets
  280. end
  281. 1 def metadata_report_keys
  282. return IGNORE_BLANK_KEY_VALUES, metadata_keys_report
  283. end
  284. 1 def metadata_report_label_override( metadata_key:, metadata_value: ) # rubocop:disable Lint/UnusedMethodArgument
  285. case metadata_key.to_s
  286. when 'file_set_ids'
  287. 'File Set IDs: '
  288. when 'total_file_count'
  289. 'Total File Count: '
  290. when 'total_file_size_human_readable'
  291. 'Total File Size: '
  292. end
  293. end
  294. 1 def metadata_report_title_pre
  295. 'DataSet: '
  296. end
  297. # # Visibility helpers
  298. # def private?
  299. # visibility == Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
  300. # end
  301. #
  302. # def public?
  303. # visibility == Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
  304. # end
  305. #
  306. # Make it so work does not show up in search result for anyone, not even admins.
  307. #
  308. 1 def entomb!( epitaph, current_user )
  309. 1 return false if tombstone.present?
  310. 1 depositor_at_tombstone = depositor
  311. 1 visibility_at_tombstone = visibility
  312. 1 self.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
  313. 1 self.depositor = depositor
  314. 1 self.tombstone = [epitaph]
  315. 1 file_sets.each do |file_set|
  316. # TODO: FileSet#entomb!
  317. file_set.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
  318. end
  319. save
  320. provenance_tombstone( current_user: current_user,
  321. epitaph: epitaph,
  322. depositor_at_tombstone: depositor_at_tombstone,
  323. visibility_at_tombstone: visibility_at_tombstone )
  324. true
  325. end
  326. # begin metadata
  327. # the list of creators is ordered
  328. 1 def creator
  329. 347 values = super
  330. 347 values = Deepblue::MetadataHelper.ordered( ordered_values: creator_ordered, values: values )
  331. 347 return values
  332. end
  333. 1 def creator=( values )
  334. 27 self.creator_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: creator_ordered, values: values )
  335. 27 super values
  336. end
  337. # the list of curation_notes_admin is ordered
  338. 1 def curation_notes_admin
  339. 317 values = super
  340. 317 values = Deepblue::MetadataHelper.ordered( ordered_values: curation_notes_admin_ordered, values: values )
  341. 317 return values
  342. end
  343. 1 def curation_notes_admin=( values )
  344. self.curation_notes_admin_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: curation_notes_admin_ordered, values: values )
  345. super values
  346. end
  347. # the list of curation_notes_user is ordered
  348. 1 def curation_notes_user
  349. 317 values = super
  350. 317 values = Deepblue::MetadataHelper.ordered( ordered_values: curation_notes_user_ordered, values: values )
  351. 317 return values
  352. end
  353. 1 def curation_notes_user=( values )
  354. self.curation_notes_user_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: curation_notes_user_ordered, values: values )
  355. super values
  356. end
  357. # the list of description is ordered
  358. 1 def description
  359. 347 values = super
  360. 347 values = Deepblue::MetadataHelper.ordered( ordered_values: description_ordered, values: values )
  361. 347 return values
  362. end
  363. 1 def description=( values )
  364. 27 self.description_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: description_ordered, values: values )
  365. 27 super values
  366. end
  367. #
  368. # the list of keyword is ordered
  369. #
  370. 1 def keyword
  371. 317 values = super
  372. 317 values = Deepblue::MetadataHelper.ordered( ordered_values: keyword_ordered, values: values )
  373. 317 return values
  374. end
  375. 1 def keyword=( values )
  376. self.keyword_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: keyword_ordered, values: values )
  377. super values
  378. end
  379. #
  380. # handle the list of language as ordered
  381. #
  382. 1 def language
  383. 317 values = super
  384. 317 values = Deepblue::MetadataHelper.ordered( ordered_values: language_ordered, values: values )
  385. 317 return values
  386. end
  387. 1 def language=( values )
  388. self.language_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: language_ordered, values: values )
  389. super values
  390. end
  391. #
  392. # handle the list of referenced_by as ordered
  393. #
  394. 1 def referenced_by
  395. 317 values = super
  396. 317 values = Deepblue::MetadataHelper.ordered( ordered_values: referenced_by_ordered, values: values )
  397. 317 return values
  398. end
  399. 1 def referenced_by=( values )
  400. self.referenced_by_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: referenced_by_ordered, values: values )
  401. super values
  402. end
  403. 1 def access_deepblue
  404. 316 values = super
  405. 316 values = Deepblue::MetadataHelper.ordered( ordered_values: access_deepblue_ordered, values: values )
  406. 316 return values
  407. end
  408. 1 def access_deepblue=( values )
  409. self.access_deepblue_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: access_deepblue_ordered, values: values )
  410. super values
  411. end
  412. # the list of title is ordered
  413. 1 def title
  414. 345 values = super
  415. 345 values = Deepblue::MetadataHelper.ordered( ordered_values: title_ordered, values: values )
  416. 345 return values
  417. end
  418. 1 def title=( values )
  419. 27 self.title_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: title_ordered, values: values )
  420. 27 super values
  421. end
  422. # end metadata
  423. 1 def total_file_count
  424. return 0 if file_set_ids.blank?
  425. file_set_ids.size
  426. end
  427. end

app/models/dissertation.rb

100.0% lines covered

5 relevant lines. 5 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work Dissertation`
  3. 1 class Dissertation < ActiveFedora::Base
  4. 1 include ::Hyrax::WorkBehavior
  5. 1 self.indexer = DissertationIndexer
  6. # Change this to restrict which works can be added as a child.
  7. # self.valid_child_concerns = []
  8. 1 validates :title, presence: { message: 'Your work must have a title.' }
  9. # This must be included at the end, because it finalizes the metadata
  10. # schema (by adding accepts_nested_attributes)
  11. #include ::Hyrax::BasicMetadata
  12. 1 include ::Deepblue::DefaultMetadata
  13. end

app/models/file_set.rb

34.78% lines covered

138 relevant lines. 48 lines covered and 90 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class FileSet < ActiveFedora::Base
  3. 1 include ::Deepblue::FileSetMetadata # must be before `include ::Hyrax::FileSetBehavior`
  4. 1 include ::Hyrax::FileSetBehavior
  5. 1 include ::Deepblue::FileSetBehavior
  6. 1 include ::Deepblue::MetadataBehavior
  7. 1 include ::Deepblue::ProvenanceBehavior
  8. 1 include ::Deepblue::EmbargoableBehavior
  9. 1 include ::Datacore::PresentsArchiveFile
  10. 1 before_destroy :provenance_before_destroy_file_set
  11. 1 def provenance_before_destroy_file_set
  12. # workflow_destroy does this
  13. # provenance_destroy( current_user: '' ) # , event_note: 'provenance_before_destroy_file_set' )
  14. end
  15. 1 def metadata_keys_all
  16. 1 %i[
  17. curation_notes_admin
  18. curation_notes_user
  19. date_created
  20. date_modified
  21. date_uploaded
  22. file_extension
  23. files_count
  24. file_size
  25. file_size_human_readable
  26. label
  27. location
  28. mime_type
  29. original_checksum
  30. original_name
  31. parent_id
  32. prior_identifier
  33. title
  34. uri
  35. version_count
  36. virus_scan_service
  37. virus_scan_status
  38. virus_scan_status_date
  39. visibility
  40. ]
  41. end
  42. 1 def metadata_keys_brief
  43. 1 %i[
  44. title
  45. label
  46. parent_id
  47. file_extension
  48. visibility
  49. ]
  50. end
  51. 1 def metadata_keys_report
  52. %i[
  53. curation_notes_user
  54. file_extension
  55. files_count
  56. file_size_human_readable
  57. label
  58. mime_type
  59. original_checksum
  60. original_name
  61. parent_id
  62. title
  63. ]
  64. end
  65. 1 def metadata_keys_update
  66. 1 %i[
  67. title
  68. label
  69. parent_id
  70. file_extension
  71. version_count
  72. visibility
  73. ]
  74. end
  75. 1 def metadata_keys_virus
  76. %i[
  77. title
  78. label
  79. parent_id
  80. file_extension
  81. virus_scan_service
  82. virus_scan_status
  83. virus_scan_status_date
  84. visibility
  85. ]
  86. end
  87. 1 def attributes_all_for_email
  88. metadata_keys_all
  89. end
  90. 1 def attributes_all_for_provenance
  91. 1 metadata_keys_all
  92. end
  93. 1 def attributes_brief_for_email
  94. metadata_keys_brief
  95. end
  96. 1 def attributes_brief_for_provenance
  97. 1 metadata_keys_brief
  98. end
  99. 1 def attributes_standard_for_email
  100. metadata_keys_brief
  101. end
  102. 1 def attributes_update_for_email
  103. metadata_keys_update
  104. end
  105. 1 def attributes_update_for_provenance
  106. 1 metadata_keys_update
  107. end
  108. 1 def attributes_virus_for_provenance
  109. metadata_keys_virus
  110. end
  111. 1 def files_to_file
  112. return nil if files.blank?
  113. files.each do |f|
  114. return f if f.original_name.present?
  115. end
  116. nil
  117. end
  118. 1 def for_provenance_route
  119. Rails.application.routes.url_helpers.hyrax_file_set_path( id: id )
  120. end
  121. 1 def title_type
  122. human_readable_type
  123. end
  124. 1 def map_provenance_attributes_override!( event:, # rubocop:disable Lint/UnusedMethodArgument
  125. attribute:,
  126. ignore_blank_key_values:,
  127. prov_key_values: )
  128. value = nil
  129. handled = case attribute.to_s
  130. when 'file_extension'
  131. value = File.extname label if label.present?
  132. true
  133. when 'files_count'
  134. value = files.size
  135. true
  136. when 'file_size'
  137. value = file_size_value
  138. true
  139. when 'file_size_human_readable'
  140. value = file_size_value
  141. value = ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert( value, precision: 3 )
  142. true
  143. when 'label'
  144. value = label
  145. true
  146. when 'mime_type'
  147. value = mime_type
  148. true
  149. when 'parent_id'
  150. value = parent.id unless parent.nil?
  151. true
  152. when 'original_checksum'
  153. value = original_checksum.blank? ? '' : original_checksum[0]
  154. true
  155. when 'original_name'
  156. value = original_name_value
  157. true
  158. when 'uri'
  159. value = uri.value
  160. true
  161. when 'version_count'
  162. value = version_count
  163. true
  164. when 'visibility'
  165. value = visibility
  166. true
  167. else
  168. false
  169. end
  170. return false unless handled
  171. if ignore_blank_key_values
  172. prov_key_values[attribute] = value if value.present?
  173. else
  174. prov_key_values[attribute] = value
  175. end
  176. return true
  177. end
  178. 1 def file_size_value
  179. if file_size.blank?
  180. original_file.nil? ? 0 : original_file.size
  181. else
  182. file_size[0]
  183. end
  184. end
  185. 1 def original_name_value
  186. return '' if original_file.nil?
  187. return original_file.original_name if original_file.respond_to?( :original_name )
  188. return ''
  189. end
  190. 1 def metadata_hash_override( key:, ignore_blank_values:, key_values: )
  191. value = nil
  192. handled = case key.to_s
  193. when 'file_extension'
  194. value = File.extname label if label.present?
  195. true
  196. when 'files_count'
  197. value = files.size
  198. true
  199. when 'file_size'
  200. value = file_size_value
  201. true
  202. when 'file_size_human_readable'
  203. value = file_size_value
  204. value = ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert( value, precision: 3 )
  205. true
  206. when 'label'
  207. value = label
  208. true
  209. when 'mime_type'
  210. value = mime_type
  211. true
  212. when 'parent_id'
  213. value = parent.id unless parent.nil?
  214. true
  215. when 'original_checksum'
  216. value = original_checksum.blank? ? '' : original_checksum[0]
  217. true
  218. when 'original_name'
  219. value = original_name_value
  220. true
  221. when 'uri'
  222. value = uri.value
  223. true
  224. when 'version_count'
  225. value = version_count
  226. true
  227. when 'visibility'
  228. value = visibility
  229. true
  230. else
  231. false
  232. end
  233. return false unless handled
  234. if ignore_blank_values
  235. key_values[key] = value if value.present?
  236. else
  237. key_values[key] = value
  238. end
  239. return true
  240. end
  241. 1 def metadata_report_keys
  242. return IGNORE_BLANK_KEY_VALUES, metadata_keys_report
  243. end
  244. 1 def metadata_report_title_pre
  245. 'FileSet: '
  246. end
  247. # begin metadata
  248. # the list of curation_notes_admin is ordered
  249. 1 def curation_notes_admin
  250. 11 values = super
  251. 11 values = Deepblue::MetadataHelper.ordered( ordered_values: curation_notes_admin_ordered, values: values )
  252. 11 return values
  253. end
  254. 1 def curation_notes_admin=( values )
  255. self.curation_notes_admin_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: curation_notes_admin_ordered, values: values )
  256. super values
  257. end
  258. # the list of curation_notes_user is ordered
  259. 1 def curation_notes_user
  260. 11 values = super
  261. 11 values = Deepblue::MetadataHelper.ordered( ordered_values: curation_notes_user_ordered, values: values )
  262. 11 return values
  263. end
  264. 1 def curation_notes_user=( values )
  265. self.curation_notes_user_ordered = Deepblue::MetadataHelper.ordered_values( ordered_values: curation_notes_user_ordered, values: values )
  266. super values
  267. end
  268. # end metadata
  269. end

app/models/generic_work.rb

100.0% lines covered

5 relevant lines. 5 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work GenericWork`
  3. 1 class GenericWork < ActiveFedora::Base
  4. 1 include ::Hyrax::WorkBehavior
  5. 1 self.indexer = GenericWorkIndexer
  6. # Change this to restrict which works can be added as a child.
  7. # self.valid_child_concerns = []
  8. 1 validates :title, presence: { message: 'Your work must have a title.' }
  9. # This must be included at the end, because it finalizes the metadata
  10. # schema (by adding accepts_nested_attributes)
  11. #include ::Hyrax::BasicMetadata
  12. 1 include ::Deepblue::DefaultMetadata
  13. end

app/models/qa/local_authority.rb

100.0% lines covered

1 relevant lines. 1 lines covered and 0 lines missed.
    
  1. 1 class Qa::LocalAuthority < ApplicationRecord
  2. end

app/models/qa/local_authority_entry.rb

100.0% lines covered

2 relevant lines. 2 lines covered and 0 lines missed.
    
  1. 1 class Qa::LocalAuthorityEntry < ApplicationRecord
  2. 1 belongs_to :local_authority
  3. end

app/models/search_builder.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class SearchBuilder < Blacklight::SearchBuilder
  3. 1 include Blacklight::Solr::SearchBuilderBehavior
  4. # Add a filter query to restrict the search to documents the current user has access to
  5. 1 include Hydra::AccessControlsEnforcement
  6. 1 include Hyrax::SearchFilters
  7. ##
  8. # @example Adding a new step to the processor chain
  9. # self.default_processor_chain += [:add_custom_data_to_query]
  10. #
  11. # def add_custom_data_to_query(solr_parameters)
  12. # solr_parameters[:custom] = blacklight_params[:user_value]
  13. # end
  14. end

app/models/solr_document.rb

52.58% lines covered

97 relevant lines. 51 lines covered and 46 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class SolrDocument
  3. 1 include Blacklight::Solr::Document
  4. # include BlacklightOaiProvider::SolrDocumentBehavior
  5. 1 include Blacklight::Gallery::OpenseadragonSolrDocument
  6. # Adds Hyrax behaviors to the SolrDocument.
  7. 1 include Hyrax::SolrDocumentBehavior
  8. 1 include Umrdr::SolrDocumentBehavior
  9. # .unique_key = 'id'
  10. # Email uses the semantic field mappings below to generate the body of an email.
  11. 1 SolrDocument.use_extension(Blacklight::Document::Email)
  12. # SMS uses the semantic field mappings below to generate the body of an SMS email.
  13. 1 SolrDocument.use_extension(Blacklight::Document::Sms)
  14. # DublinCore uses the semantic field mappings below to assemble an OAI-compliant Dublin Core document
  15. # Semantic mappings of solr stored fields. Fields may be multi or
  16. # single valued. See Blacklight::Document::SemanticFields#field_semantics
  17. # and Blacklight::Document::SemanticFields#to_semantic_values
  18. # Recommendation: Use field names from Dublin Core
  19. 1 use_extension(Blacklight::Document::DublinCore)
  20. # This fails to load.
  21. # use_extension(::ScholarsArchive::Document::QualifiedDublinCore)
  22. # Do content negotiation for AF models.
  23. 1 use_extension( Hydra::ContentNegotiation )
  24. 1 def self.solrized_methods(property_names)
  25. 1 property_names.each do |property_name|
  26. 83 define_method property_name.to_sym do
  27. self[Solrizer.solr_name(property_name)]
  28. end
  29. end
  30. end
  31. 1 def academic_affiliation_label
  32. # references to ScholarsArchive raise ActionView::Template::Error (uninitialized constant SolrDocument::ScholarsArchive)
  33. # ScholarsArchive::LabelParserService.parse_label_uris(self['academic_affiliation_label_ssim'])
  34. self['academic_affiliation_label_ssim']
  35. end
  36. 1 def curation_notes_admin_label
  37. self['curation_notes_admin_label_ssim']
  38. end
  39. 1 def curation_notes_user_label
  40. self['curation_notes_user_label_ssim']
  41. end
  42. 1 def date_published_label
  43. self['date_published_dtsim']
  44. end
  45. 1 def degree_field_label
  46. # references to ScholarsArchive raise ActionView::Template::Error (uninitialized constant SolrDocument::ScholarsArchive)
  47. # ScholarsArchive::LabelParserService.parse_label_uris(self['degree_field_label_ssim'])
  48. self['degree_field_label_ssim']
  49. end
  50. 1 def degree_grantors_label
  51. # references to ScholarsArchive raise ActionView::Template::Error (uninitialized constant SolrDocument::ScholarsArchive)
  52. # ScholarsArchive::LabelParserService.parse_label_uris(self['degree_grantors_label_ssim'])
  53. self['degree_grantors_label_ssim']
  54. end
  55. 1 def doi_label
  56. self['doi_label_ssim']
  57. end
  58. 1 def access_deepblue_label
  59. self['access_deepblue_label_ssim']
  60. end
  61. 1 def fundedby_label
  62. self['fundedby_label_ssim']
  63. end
  64. 1 def fundedby_other_label
  65. self['fundedby_other_label_ssim']
  66. end
  67. 1 def grantnumber_label
  68. self['grantnumber_label_ssim']
  69. end
  70. 1 def referenced_by_label
  71. self['referenced_by_label_ssim']
  72. end
  73. 1 def language_label
  74. self['language_label_ssim']
  75. end
  76. 1 def license_label
  77. self['license_label_ssim']
  78. end
  79. 1 def methodology_label
  80. self['methodology_label_ssim']
  81. end
  82. 1 def nested_geo
  83. self[Solrizer.solr_name('nested_geo_label', :symbol)] || []
  84. end
  85. 1 def nested_related_items_label
  86. # references to ScholarsArchive raise ActionView::Template::Error (uninitialized constant SolrDocument::ScholarsArchive)
  87. # ScholarsArchive::LabelParserService.parse_label_uris(self[Solrizer.solr_name('nested_related_items_label', :symbol)]) || []
  88. self[Solrizer.solr_name('nested_related_items_label', :symbol)] || []
  89. end
  90. 1 def other_affiliation_label
  91. # references to ScholarsArchive raise ActionView::Template::Error (uninitialized constant SolrDocument::ScholarsArchive)
  92. # ScholarsArchive::LabelParserService.parse_label_uris(self['other_affiliation_label_ssim'])
  93. self['other_affiliation_label_ssim']
  94. end
  95. 1 def peerreviewed_label
  96. self['peerreviewed_label_ssim']
  97. end
  98. 1 def prior_identifier_label
  99. self['prior_identifier_label_ssim']
  100. end
  101. 1 def rights_license_label
  102. self['rights_license_label_ssim']
  103. end
  104. 1 def rights_license_other_label
  105. self['rights_license_other_label_ssim']
  106. end
  107. 1 def rights_statement_label
  108. self['rights_statement_label_ssim']
  109. end
  110. 1 def subject_discipline_label
  111. self['subject_discipline_label_ssim']
  112. end
  113. 1 def system_created
  114. Time.parse self['system_create_dtsi']
  115. end
  116. 1 def geo_location_place
  117. self['geo_location_place_tesim'] || []
  118. end
  119. 1 def geo_location_box
  120. self['geo_location_box_tesim'] || []
  121. end
  122. 1 def license_other
  123. self['license_other_tesim'] || []
  124. end
  125. 1 solrized_methods [
  126. 'abstract',
  127. 'academic_affiliation',
  128. 'additional_information',
  129. 'description_abstract',
  130. 'language_none',
  131. 'peerreviewed',
  132. 'alt_title',
  133. 'bibliographic_citation',
  134. 'conference_location',
  135. 'conference_name',
  136. 'conference_section',
  137. 'contributor_advisor',
  138. 'contributor_affiliationumcampus',
  139. 'contributor_author',
  140. 'contributor_committeemember',
  141. 'curation_notes_admin',
  142. 'curation_notes_user',
  143. 'date_accepted',
  144. 'date_available',
  145. 'date_collected',
  146. 'date_copyright',
  147. 'date_issued',
  148. 'date_published',
  149. 'date_reviewed',
  150. 'date_submitted',
  151. 'date_valid',
  152. 'degree_discipline',
  153. 'degree_field',
  154. 'degree_grantors',
  155. 'degree_level',
  156. 'degree_name',
  157. 'description_mapping',
  158. 'description_sponsorship',
  159. 'description_thesisdegreediscipline',
  160. 'description_thesisdegreegrantor',
  161. 'description_thesisdegreename',
  162. 'digitization_spec',
  163. 'doi',
  164. 'dspace_collection',
  165. 'dspace_community',
  166. 'duration',
  167. 'editor',
  168. 'embargo_reason',
  169. 'file_extent',
  170. 'file_format',
  171. 'fundedby',
  172. 'fundedby_other',
  173. 'funding_body',
  174. 'funding_statement',
  175. 'graduation_year',
  176. 'grantnumber',
  177. 'has_journal',
  178. 'has_number',
  179. 'has_volume',
  180. 'hydrologic_unit_code',
  181. 'identifier',
  182. 'identifier_orcid',
  183. 'identifier_source',
  184. 'identifier_uniqname',
  185. 'in_series',
  186. 'interactivity_type',
  187. 'is_based_on_url',
  188. 'referenced_by',
  189. 'isbn',
  190. 'issn',
  191. 'language',
  192. 'learning_resource_type',
  193. 'methodology',
  194. 'other_affiliation',
  195. 'prior_identifier',
  196. 'relation_ispartofseries',
  197. 'replaces',
  198. 'rights_license',
  199. 'rights_license_other',
  200. 'subject_discipline',
  201. 'subject_other',
  202. 'tableofcontents',
  203. 'time_required',
  204. 'type_none',
  205. 'typical_age_range',
  206. 'virus_scan_service',
  207. 'virus_scan_status',
  208. 'virus_scan_status_date'
  209. ]
  210. 1 field_semantics.merge!(
  211. contributor: [ 'contributor_tesim',
  212. 'editor_tesim',
  213. 'contributor_advisor_tesim',
  214. 'contributor_committeemember_tesim',
  215. 'oai_academic_affiliation_label',
  216. 'oai_other_affiliation_label' ],
  217. coverage: ['based_near_label_tesim', 'conferenceLocation_tesim'],
  218. creator: 'creator_tesim',
  219. date: 'date_created_tesim',
  220. description: ['description_tesim', 'abstract_tesim'],
  221. format: ['file_extent_tesim', 'file_format_tesim'],
  222. identifier: 'oai_identifier',
  223. language: 'language_label_tesim',
  224. publisher: 'publisher_tesim',
  225. relation: 'oai_nested_related_items_label',
  226. rights: 'oai_rights',
  227. source: ['source_tesim', 'isBasedOnUrl_tesim'],
  228. subject: ['subject_tesim', 'keyword_tesim'],
  229. title: 'title_tesim',
  230. type: 'resource_type_tesim'
  231. )
  232. # Override SolrDocument hash access for certain virtual fields
  233. 1 def [](key)
  234. 5 return send(key) if [ 'oai_academic_affiliation_label',
  235. 'oai_other_affiliation_label',
  236. 'oai_rights',
  237. 'oai_identifier',
  238. 'oai_nested_related_items_label' ].include?(key)
  239. 5 super
  240. end
  241. 1 def sets
  242. fetch('isPartOf', []).map { |m| BlacklightOaiProvider::Set.new("isPartOf_ssim:#{m}") }
  243. end
  244. 1 def oai_nested_related_items_label
  245. related_items = []
  246. nested_related_items_label&.each do |r|
  247. related_items << r["label"] + ': ' + r["uri"]
  248. end
  249. related_items
  250. end
  251. 1 def oai_academic_affiliation_label
  252. aa_labels = []
  253. academic_affiliation_label&.each do |a|
  254. aa_labels << a["label"]
  255. end
  256. aa_labels
  257. end
  258. 1 def oai_other_affiliation_label
  259. oa_labels = []
  260. other_affiliation_label&.each do |o|
  261. oa_labels << o["label"]
  262. end
  263. oa_labels
  264. end
  265. # Only return License if present, otherwise Rights
  266. 1 def oai_rights
  267. license_label ? license_label : rights_statement_label
  268. end
  269. 1 def oai_identifier
  270. if self["has_model_ssim"].first.to_s == "Collection"
  271. Hyrax::Engine.routes.url_helpers.url_for( only_path: false,
  272. action: 'show',
  273. host: CatalogController.blacklight_config.oai[:provider][:repository_url],
  274. controller: 'hyrax/collections',
  275. id: id )
  276. else
  277. Rails.application.routes.url_helpers.url_for( only_path: false,
  278. action: 'show',
  279. host: CatalogController.blacklight_config.oai[:provider][:repository_url],
  280. controller: 'hyrax/' + self["has_model_ssim"].first.to_s.underscore.pluralize,
  281. id: id )
  282. end
  283. end
  284. end

app/models/user.rb

63.64% lines covered

22 relevant lines. 14 lines covered and 8 lines missed.
    
  1. 1 class User < ApplicationRecord
  2. # Connects this user object to Hydra behaviors.
  3. 1 include Hydra::User
  4. # Connects this user object to Role-management behaviors.
  5. 1 include Hydra::RoleManagement::UserRoles
  6. # Connects this user object to Hyrax behaviors.
  7. 1 include Hyrax::User
  8. 1 include Hyrax::UserUsageStats
  9. # Use the http header as auth. This app will be behind a reverse proxy
  10. # that will take care of the authentication.
  11. 1 Devise.add_module(:http_header_authenticatable,
  12. strategy: true,
  13. controller: :sessions,
  14. model: 'devise/models/http_header_authenticatable')
  15. 1 if Rails.configuration.authentication_method == "iu"
  16. 1 devise :omniauthable, :omniauth_providers => [:cas]
  17. 1 alias_attribute :ldap_lookup_key, :uid
  18. 1 include LDAPGroupsLookup::Behavior
  19. else
  20. devise :database_authenticatable, :registerable,
  21. :recoverable, :rememberable, :trackable, :validatable
  22. end
  23. 1 if Blacklight::Utils.needs_attr_accessible?
  24. attr_accessible :email, :password, :password_confirmation
  25. end
  26. # Connects this user object to Blacklights Bookmarks.
  27. 1 include Blacklight::User
  28. # Include default devise modules. Others available are:
  29. # :confirmable, :lockable, :timeoutable and :omniauthable
  30. # Method added by Blacklight; Blacklight uses #to_s on your
  31. # user class to get a user-displayable login/identifier for
  32. # the account.
  33. 1 def to_s
  34. email
  35. end
  36. # helper for IU auth
  37. 1 def self.find_for_iu_cas(auth)
  38. where(provider: auth.provider, uid: auth.uid).first_or_create! do |user|
  39. user.provider = auth.provider
  40. user.uid = auth.uid
  41. user.email = [auth.uid,'@iu.edu'].join
  42. user.encrypted_password = Devise.friendly_token[0,20]
  43. end
  44. end
  45. end

app/presenters/concerns/datacore/presents_archive_file.rb

45.83% lines covered

24 relevant lines. 11 lines covered and 13 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Datacore
  3. 1 module PresentsArchiveFile
  4. # archive files bypass fedora storage
  5. 1 def archive_file?
  6. mime_type.to_s.match(/^message\/external-body\;.*access-type=URL/).present?
  7. end
  8. # needs to pass through archive_file in case any / to %2F encoding happened there
  9. 1 def archive_request_url
  10. @archive_request_url ||= begin
  11. return '/' unless archive_file?
  12. archive_file.send(:request_url)
  13. end
  14. end
  15. 1 def archive_status_url
  16. archive_request_url.sub('/request/', '/status/')
  17. end
  18. 1 def archive_file
  19. @archive_file ||=
  20. if archive_file?
  21. # nested objects may be stored in format:
  22. # /sda/request/<collection>/<subdir>%2F<object>
  23. # which works rails routing, but we need to force-encode the final '/' if stored as:
  24. # /sda/request/<collection>/<subdir>/<object>
  25. collection_and_object = mime_type.split('"').last.sub('/sda/request/', '').split('/')
  26. collection = collection_and_object.first
  27. object = collection_and_object[1, collection_and_object.size].join('%2F')
  28. ArchiveFile.new(collection: collection, object: object)
  29. end
  30. end
  31. 1 delegate :display_status, :request_action, :request_actionable?, :request_for_staging?, :status_in_ui, to: :archive_file, allow_nil: true
  32. 1 alias_method :archive_status_description, :display_status
  33. 1 alias_method :archive_status_code, :status_in_ui
  34. 1 def provide_request_email?
  35. Settings.archive_api.provide_email.present?
  36. end
  37. 1 def require_request_email?
  38. Settings.archive_api.provide_email == :required
  39. end
  40. end
  41. end

app/presenters/guest_user_message_presenter.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class GuestUserMessagePresenter
  3. 1 attr_accessor :controller
  4. 1 def initialize( controller: )
  5. 1 @controller = controller
  6. end
  7. end

app/presenters/hyrax/characterization_behavior.rb

45.76% lines covered

59 relevant lines. 27 lines covered and 32 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. # TODO: monkey patch this to only override and provide necessary behavior
  4. 1 module CharacterizationBehavior
  5. 1 extend ActiveSupport::Concern
  6. 1 class_methods do
  7. 1 def characterization_terms
  8. 1 [
  9. :byte_order,
  10. :compression,
  11. :height,
  12. :width,
  13. :height,
  14. :color_space,
  15. :profile_name,
  16. :profile_version,
  17. :orientation,
  18. :color_map,
  19. :image_producer,
  20. :capture_device,
  21. :scanning_software,
  22. :gps_timestamp,
  23. :latitude,
  24. :longitude,
  25. :file_format,
  26. :file_title,
  27. :page_count,
  28. :duration,
  29. :sample_rate,
  30. :format_label,
  31. # :file_size, # replace this with
  32. :file_size_human_readable, # replaces file size
  33. :filename,
  34. :well_formed,
  35. :last_modified,
  36. :original_checksum, # TODO: revisit this...
  37. :mime_type
  38. ]
  39. end
  40. 1 def characterization_terms_admin_only
  41. 1 %i[
  42. virus_scan_service
  43. virus_scan_status
  44. virus_scan_status_date
  45. ]
  46. end
  47. end
  48. 1 included do
  49. 1 delegate( *characterization_terms, to: :solr_document )
  50. 1 delegate( *characterization_terms_admin_only, to: :solr_document )
  51. end
  52. 1 def characterized?
  53. !characterization_metadata.values.compact.empty?
  54. end
  55. 1 def characterization_metadata
  56. @characterization_metadata ||= build_characterization_metadata
  57. end
  58. 1 def characterization_metadata_admin_only
  59. @characterization_metadata_admin_only ||= build_characterization_metadata_admin_only
  60. end
  61. # Override this if you want to inject additional characterization metadata
  62. # Use a hash of key/value pairs where the value is an Array or String
  63. # {
  64. # term1: ["value"],
  65. # term2: ["value1", "value2"],
  66. # term3: "a string"
  67. # }
  68. 1 def additional_characterization_metadata
  69. @additional_characterization_metadata ||= {}
  70. end
  71. 1 def additional_characterization_metadata_admin_only
  72. @additional_characterization_metadata_admin_only ||= {}
  73. end
  74. 1 def label_for_term( term )
  75. MsgHelper.t( "show.file_set.label.#{term}", raise: true )
  76. rescue I18n::MissingTranslationData => e
  77. term.to_s.titleize
  78. end
  79. # Returns an array of characterization values truncated to 250 characters limited
  80. # to the maximum number of configured values.
  81. # @param [Symbol] term found in the characterization_metadata hash
  82. # @return [Array] of truncated values
  83. 1 def primary_characterization_values( term )
  84. values = values_for( term )
  85. values.slice!(Hyrax.config.fits_message_length, (values.length - Hyrax.config.fits_message_length))
  86. truncate_all(values)
  87. end
  88. # Returns an array of characterization values truncated to 250 characters limited
  89. # to the maximum number of configured values.
  90. # @param [Symbol] term found in the characterization_metadata hash
  91. # @return [Array] of truncated values
  92. 1 def primary_characterization_values_admin_only( term )
  93. values = values_for_admin_only( term )
  94. values.slice!(Hyrax.config.fits_message_length, (values.length - Hyrax.config.fits_message_length))
  95. truncate_all(values)
  96. end
  97. # Returns an array of characterization values truncated to 250 characters that are in
  98. # excess of the maximum number of configured values.
  99. # @param [Symbol] term found in the characterization_metadata hash
  100. # @return [Array] of truncated values
  101. 1 def secondary_characterization_values(term)
  102. values = values_for(term)
  103. additional_values = values.slice(Hyrax.config.fits_message_length, values.length - Hyrax.config.fits_message_length)
  104. return [] unless additional_values
  105. truncate_all(additional_values)
  106. end
  107. # Returns an array of characterization values truncated to 250 characters that are in
  108. # excess of the maximum number of configured values.
  109. # @param [Symbol] term found in the characterization_metadata hash
  110. # @return [Array] of truncated values
  111. 1 def secondary_characterization_values_admin_only(term)
  112. values = values_for_admin_only(term)
  113. additional_values = values.slice(Hyrax.config.fits_message_length, values.length - Hyrax.config.fits_message_length)
  114. return [] unless additional_values
  115. truncate_all(additional_values)
  116. end
  117. 1 private
  118. 1 def values_for( term )
  119. Array.wrap( characterization_metadata[term] )
  120. end
  121. 1 def values_for_admin_only( term )
  122. Array.wrap( characterization_metadata_admin_only[term] )
  123. end
  124. 1 def truncate_all(values)
  125. values.map { |v| v.to_s.truncate(250) }
  126. end
  127. 1 def build_characterization_metadata
  128. self.class.characterization_terms.each do |term|
  129. value = send(term)
  130. additional_characterization_metadata[term.to_sym] = value if value.present?
  131. end
  132. additional_characterization_metadata
  133. end
  134. 1 def build_characterization_metadata_admin_only
  135. self.class.characterization_terms_admin_only.each do |term|
  136. value = send(term)
  137. additional_characterization_metadata_admin_only[term.to_sym] = value if value.present?
  138. end
  139. additional_characterization_metadata_admin_only
  140. end
  141. end
  142. end

app/presenters/hyrax/collection_presenter.rb

46.81% lines covered

94 relevant lines. 44 lines covered and 50 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 class CollectionPresenter
  4. 1 include ModelProxy
  5. 1 include PresentsAttributes
  6. 1 include ActionView::Helpers::NumberHelper
  7. 1 include ::Hyrax::BrandingHelper
  8. 1 attr_accessor :solr_document, :current_ability, :request
  9. 1 attr_reader :subcollection_count
  10. 1 attr_accessor :parent_collections # This is expected to be a Blacklight::Solr::Response with all of the parent collections
  11. 1 attr_writer :collection_type
  12. 1 class_attribute :create_work_presenter_class
  13. 1 self.create_work_presenter_class = Hyrax::SelectTypeListPresenter
  14. # @param [SolrDocument] solr_document
  15. # @param [Ability] current_ability
  16. # @param [ActionDispatch::Request] request the http request context
  17. 1 def initialize(solr_document, current_ability, request = nil)
  18. @solr_document = solr_document
  19. @current_ability = current_ability
  20. @request = request
  21. @subcollection_count = 0
  22. end
  23. # CurationConcern methods
  24. 1 delegate :stringify_keys, :human_readable_type, :collection?, :representative_id,
  25. :to_s, to: :solr_document
  26. 1 delegate(*Hyrax::CollectionType.collection_type_settings_methods, to: :collection_type, prefix: :collection_type_is)
  27. 1 def collection_type
  28. @collection_type ||= Hyrax::CollectionType.find_by_gid!(collection_type_gid)
  29. end
  30. # Metadata Methods
  31. 1 delegate :title, :description, :creator, :contributor, :subject, :publisher, :keyword, :language, :embargo_release_date,
  32. :lease_expiration_date, :license, :date_created, :resource_type, :based_near, :related_url, :identifier, :thumbnail_path,
  33. :title_or_label, :collection_type_gid, :create_date, :modified_date, :visibility, :edit_groups, :edit_people,
  34. to: :solr_document
  35. # Terms is the list of fields displayed by
  36. # app/views/collections/_show_descriptions.html.erb
  37. 1 def self.terms
  38. [:total_items, :size, :resource_type, :creator, :contributor, :keyword, :license, :publisher, :date_created, :subject,
  39. :language, :identifier, :based_near, :related_url]
  40. end
  41. 1 def terms_with_values
  42. self.class.terms.select { |t| self[t].present? }
  43. end
  44. 1 def [](key)
  45. case key
  46. when :size
  47. size
  48. when :total_items
  49. total_items
  50. else
  51. solr_document.send key
  52. end
  53. end
  54. # begin display_provenance_log
  55. 1 def display_provenance_log_enabled?
  56. true
  57. end
  58. 1 def provenance_log_entries?
  59. file_path = Deepblue::ProvenancePath.path_for_reference( id )
  60. File.exist? file_path
  61. end
  62. # end display_provenance_log
  63. 1 def relative_url_root
  64. rv = ::DeepBlueDocs::Application.config.relative_url_root
  65. return rv if rv
  66. ''
  67. end
  68. 1 def size
  69. number_to_human_size(@solr_document['bytes_lts'])
  70. end
  71. 1 def total_items
  72. ActiveFedora::Base.where("member_of_collection_ids_ssim:#{id}").count
  73. end
  74. 1 def total_viewable_items
  75. ActiveFedora::Base.where("member_of_collection_ids_ssim:#{id}").accessible_by(current_ability).count
  76. end
  77. 1 def total_viewable_works
  78. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  79. ::Deepblue::LoggingHelper.called_from,
  80. "id=#{id}",
  81. "current_ability=#{current_ability}",
  82. "" ]
  83. ActiveFedora::Base.where("member_of_collection_ids_ssim:#{id} AND generic_type_sim:Work").accessible_by(current_ability).count
  84. end
  85. 1 def total_viewable_collections
  86. ActiveFedora::Base.where("member_of_collection_ids_ssim:#{id} AND generic_type_sim:Collection").accessible_by(current_ability).count
  87. end
  88. 1 def collection_type_badge
  89. collection_type.title
  90. end
  91. # The total number of parents that this collection belongs to, visible or not.
  92. 1 def total_parent_collections
  93. parent_collections.nil? ? 0 : parent_collections.response['numFound']
  94. end
  95. # The number of parent collections shown on the current page. This will differ from total_parent_collections
  96. # due to pagination.
  97. 1 def parent_collection_count
  98. parent_collections.nil? ? 0 : parent_collections.documents.size
  99. end
  100. 1 def user_can_nest_collection?
  101. current_ability.can?(:deposit, solr_document)
  102. end
  103. 1 def user_can_create_new_nest_collection?
  104. current_ability.can?(:create_collection_of_type, collection_type)
  105. end
  106. 1 def show_path
  107. Hyrax::Engine.routes.url_helpers.dashboard_collection_path(id)
  108. end
  109. 1 def banner_file
  110. branding_banner_file( id: id )
  111. end
  112. 1 def logo_record
  113. branding_logo_record( id: id )
  114. end
  115. # A presenter for selecting a work type to create
  116. # this is needed here because the selector is in the header on every page
  117. 1 def create_work_presenter
  118. @create_work_presenter ||= create_work_presenter_class.new(current_ability.current_user)
  119. end
  120. 1 def create_many_work_types?
  121. if Flipflop.only_use_data_set_work_type?
  122. false
  123. else
  124. create_work_presenter.many?
  125. end
  126. end
  127. 1 def draw_select_work_modal?
  128. create_many_work_types?
  129. end
  130. 1 def first_work_type
  131. create_work_presenter.first_model
  132. end
  133. 1 def available_parent_collections(scope:)
  134. return @available_parents if @available_parents.present?
  135. collection = Collection.find(id)
  136. colls = Hyrax::Collections::NestedCollectionQueryService.available_parent_collections(child: collection, scope: scope, limit_to_id: nil)
  137. @available_parents = colls.map do |col|
  138. { "id" => col.id, "title_first" => col.title.first }
  139. end
  140. @available_parents.to_json
  141. end
  142. 1 def subcollection_count=(total)
  143. @subcollection_count = total unless total.nil?
  144. end
  145. # For the Managed Collections tab, determine the label to use for the level of access the user has for this admin set.
  146. # Checks from most permissive to most restrictive.
  147. # @return String the access label (e.g. Manage, Deposit, View)
  148. 1 def managed_access
  149. return I18n.t('hyrax.dashboard.my.collection_list.managed_access.manage') if current_ability.can?(:edit, solr_document)
  150. return I18n.t('hyrax.dashboard.my.collection_list.managed_access.deposit') if current_ability.can?(:deposit, solr_document)
  151. return I18n.t('hyrax.dashboard.my.collection_list.managed_access.view') if current_ability.can?(:read, solr_document)
  152. ''
  153. end
  154. # Determine if the user can perform batch operations on this collection. Currently, the only
  155. # batch operation allowed is deleting, so this is equivalent to checking if the user can delete
  156. # the collection determined by criteria...
  157. # * user must be able to edit the collection to be able to delete it
  158. # * the collection does not have to be empty
  159. # @return Boolean true if the user can perform batch actions; otherwise, false
  160. 1 def allow_batch?
  161. return true if current_ability.can?(:edit, solr_document)
  162. false
  163. end
  164. end
  165. end

app/presenters/hyrax/data_set_presenter.rb

35.82% lines covered

67 relevant lines. 24 lines covered and 43 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 class DataSetPresenter < DeepbluePresenter
  4. 1 delegate :authoremail,
  5. :curation_notes_admin,
  6. :curation_notes_user,
  7. :date_coverage,
  8. :date_published, :date_published2, # FIXME; investigate
  9. :doi, :doi_the_correct_one, # FIXME: investigate
  10. :doi_minted?,
  11. :doi_minting_enabled?,
  12. :doi_pending?,
  13. :fundedby,
  14. :fundedby_other,
  15. :grantnumber,
  16. :methodology,
  17. :prior_identifier,
  18. :referenced_by,
  19. :rights_license,
  20. :rights_license_other,
  21. :subject_discipline,
  22. :total_file_size,
  23. :access_deepblue,
  24. :geo_location_place,
  25. :geo_location_box,
  26. :license_other,
  27. :academic_affiliation,
  28. :alt_title,
  29. :bibliographic_citation,
  30. :contributor_affiliationumcampus,
  31. :date_attribute,
  32. :date_issued,
  33. :description_abstract,
  34. :description_mapping,
  35. :description_sponsorship,
  36. :external_link,
  37. :identifier_orcid,
  38. :identifier_source,
  39. :language_none,
  40. :linked,
  41. :other_affiliation,
  42. :peerreviewed,
  43. :relation_ispartofseries,
  44. :type_none,
  45. to: :solr_document
  46. # def initialize( solr_document, current_ability, request = nil )
  47. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  48. # Deepblue::LoggingHelper.called_from,
  49. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  50. # "solr_document = #{solr_document}",
  51. # "solr_document.class.name = #{solr_document.class.name}",
  52. # "current_ability = #{current_ability}",
  53. # "request = #{request}",
  54. # "" ]
  55. # super( solr_document, current_ability, request )
  56. # ::Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  57. # Deepblue::LoggingHelper.called_from,
  58. # Deepblue::LoggingHelper.obj_class( 'class', self ),
  59. # "@solr_document.class.name = #{@solr_document.class.name}",
  60. # "@solr_document.doi = #{@solr_document.doi}",
  61. # "@solr_document.doi_the_correct_one = #{@solr_document.doi_the_correct_one}",
  62. # "@solr_document.doi_minted? = #{@solr_document.doi_minted?}",
  63. # "@solr_document.doi_minting_enabled? = #{@solr_document.doi_minting_enabled?}",
  64. # "@solr_document.doi_pending? = #{@solr_document.doi_pending?}",
  65. # "" ]
  66. # end
  67. # begin box
  68. 1 def box_enabled?
  69. DeepBlueDocs::Application.config.box_integration_enabled
  70. end
  71. 1 def box_link( only_if_exists_in_box: false )
  72. return nil unless box_enabled?
  73. concern_id = @solr_document.id
  74. return ::BoxHelper.box_link( concern_id, only_if_exists_in_box: only_if_exists_in_box )
  75. end
  76. 1 def box_link_display_for_work?( current_user )
  77. return false unless box_enabled?
  78. rv = ::BoxHelper.box_link_display_for_work?( work_id: @solr_document.id,
  79. work_file_count: total_file_count,
  80. is_admin: current_ability.admin?,
  81. user_email: Deepblue::EmailHelper.user_email_from( current_user ) )
  82. return rv
  83. end
  84. # end box
  85. # display date range as from_date To to_date
  86. 1 def date_coverage
  87. solr_value = @solr_document.date_coverage
  88. return nil if solr_value.blank?
  89. return solr_value.sub( "/open", "" ) if solr_value.match "/open" # rubocop:disable Performance/RedundantMatch, Performance/RegexpMatch
  90. solr_value.sub( "/", " to " )
  91. end
  92. # begin display_provenance_log
  93. 1 def display_provenance_log_enabled?
  94. true
  95. end
  96. 1 def provenance_log_entries?
  97. file_path = Deepblue::ProvenancePath.path_for_reference( id )
  98. File.exist? file_path
  99. end
  100. # end display_provenance_log
  101. # begin doi
  102. #
  103. # def doi
  104. # solr_value = @solr_document[Solrizer.solr_name('doi', :symbol)]
  105. # return nil if solr_value.blank?
  106. # solr_value.first
  107. # end
  108. #
  109. # def doi_minted?
  110. # !doi.nil?
  111. # rescue
  112. # nil
  113. # end
  114. #
  115. # def doi_pending?
  116. # doi == ::Deepblue::DoiBehavior::DOI_PENDING
  117. # end
  118. #
  119. # def mint_doi_enabled?
  120. # true
  121. # end
  122. #
  123. # end doi
  124. # begin globus
  125. 1 def globus_download_enabled?
  126. DeepBlueDocs::Application.config.globus_enabled
  127. end
  128. 1 def globus_enabled?
  129. DeepBlueDocs::Application.config.globus_enabled
  130. end
  131. 1 def globus_external_url
  132. concern_id = @solr_document.id
  133. ::GlobusJob.external_url concern_id
  134. end
  135. 1 def globus_files_available?
  136. concern_id = @solr_document.id
  137. ::GlobusJob.files_available? concern_id
  138. end
  139. 1 def globus_files_prepping?
  140. concern_id = @solr_document.id
  141. ::GlobusJob.files_prepping? concern_id
  142. end
  143. 1 def globus_last_error_msg
  144. concern_id = @solr_document.id
  145. ::GlobusJob.error_file_contents concern_id
  146. end
  147. # end globus
  148. 1 def hdl
  149. # @object_profile[:hdl]
  150. end
  151. 1 def human_readable( value )
  152. ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert( value, precision: 3 )
  153. end
  154. 1 def label_with_total_file_size( label )
  155. total = total_file_size
  156. return label if total.zero?
  157. count = total_file_count
  158. files = 1 == count ? 'file' : 'files'
  159. "#{label} (#{total_file_size_human_readable} in #{count} #{files})"
  160. end
  161. # begin tombstone
  162. 1 def tombstone
  163. return nil if @solr_document.blank?
  164. solr_value = @solr_document[Solrizer.solr_name('tombstone', :symbol)]
  165. return nil if solr_value.blank?
  166. solr_value.first
  167. end
  168. 1 def tombstone_enabled?
  169. true
  170. end
  171. # end tombstone
  172. 1 def total_file_count
  173. solr_value = @solr_document[Solrizer.solr_name('file_set_ids', :symbol)]
  174. return 0 if solr_value.blank?
  175. solr_value.size
  176. end
  177. 1 def total_file_size
  178. solr_value = @solr_document[Solrizer.solr_name('total_file_size', Hyrax::FileSetIndexer::STORED_LONG)]
  179. return 0 if solr_value.blank?
  180. solr_value
  181. end
  182. 1 def total_file_size_human_readable
  183. human_readable( total_file_size )
  184. end
  185. 1 def zip_download_enabled?
  186. Settings.zip_download_enabled
  187. end
  188. end
  189. end

app/presenters/hyrax/deepblue_presenter.rb

64.29% lines covered

14 relevant lines. 9 lines covered and 5 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 class DeepbluePresenter < Hyrax::WorkShowPresenter
  4. 1 def box_enabled?
  5. false
  6. end
  7. 1 def display_provenance_log_enabled?
  8. false
  9. end
  10. 1 def doi_minting_enabled?
  11. false
  12. end
  13. 1 def globus_download_enabled?
  14. false
  15. end
  16. 1 def human_readable_type
  17. 1 "Work"
  18. end
  19. # def mint_doi_enabled?
  20. # false
  21. # end
  22. # def tombstone_enabled?
  23. # false
  24. # end
  25. 1 def zip_download_enabled?
  26. false
  27. end
  28. end
  29. end

app/presenters/hyrax/dissertation_presenter.rb

100.0% lines covered

2 relevant lines. 2 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 class DissertationPresenter < DeepbluePresenter
  4. end
  5. end

app/presenters/hyrax/ds_file_set_presenter.rb

38.24% lines covered

34 relevant lines. 13 lines covered and 21 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 class DsFileSetPresenter < Hyrax::FileSetPresenter
  4. 1 include ::Datacore::PresentsArchiveFile
  5. 1 delegate :doi, :doi_the_correct_one,
  6. :doi_minted?,
  7. :doi_minting_enabled?,
  8. :doi_pending?,
  9. :file_size,
  10. :file_size_human_readable,
  11. :original_checksum,
  12. :mime_type,
  13. :title,
  14. :virus_scan_service,
  15. :virus_scan_status,
  16. :virus_scan_status_date, to: :solr_document
  17. # def doi_minted?
  18. # # the first time this is called, doi will not be in solr.
  19. # @solr_document[ Solrizer.solr_name( 'doi', :symbol ) ].first
  20. # rescue
  21. # nil
  22. # end
  23. #
  24. # def doi_pending?
  25. # @solr_document[ Solrizer.solr_name( 'doi', :symbol ) ].first == ::Deepblue::DoiBehavior::DOI_PENDING
  26. # end
  27. 1 def relative_url_root
  28. rv = ::DeepBlueDocs::Application.config.relative_url_root
  29. return rv if rv
  30. ''
  31. end
  32. 1 def parent_doi_minted?
  33. g = DataSet.find parent.id
  34. g.doi_minted?
  35. end
  36. # begin display_provenance_log
  37. 1 def display_provenance_log_enabled?
  38. true
  39. end
  40. 1 def provenance_log_entries?
  41. file_path = Deepblue::ProvenancePath.path_for_reference( id )
  42. File.exist? file_path
  43. end
  44. # end display_provenance_log
  45. 1 def parent_public?
  46. g = DataSet.find parent.id
  47. g.public?
  48. end
  49. 1 def first_title
  50. title.first || 'File'
  51. end
  52. # To handle large files.
  53. 1 def link_name
  54. if ( current_ability.admin? || current_ability.can?(:read, id) )
  55. first_title
  56. else
  57. 'File'
  58. end
  59. end
  60. 1 def file_name( parent_presenter, link_to )
  61. if parent_presenter.tombstone.present?
  62. rv = link_name
  63. elsif file_size_too_large_to_download?
  64. rv = link_name
  65. else
  66. rv = link_to
  67. end
  68. return rv
  69. end
  70. 1 def file_size_too_large_to_download?
  71. !@solr_document.file_size.nil? && @solr_document.file_size >= DeepBlueDocs::Application.config.max_work_file_size_to_download
  72. end
  73. end
  74. end

app/presenters/hyrax/generic_work_presenter.rb

100.0% lines covered

3 relevant lines. 3 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work GenericWork`
  3. 1 module Hyrax
  4. 1 class GenericWorkPresenter < Hyrax::WorkShowPresenter
  5. 1 delegate :identifier_orcid, :academic_affiliation, :other_affiliation, :contributor_affiliationumcampus, :alt_title, :date_issued, :identifier_source, :peerreviewed, :bibliographic_citation, :relation_ispartofseries, :rights_statement, :type_none, :language_none, :description_mapping, :description_abstract, :description_sponsorship, :description, to: :solr_document
  6. end
  7. end

app/presenters/hyrax/work_show_presenter.rb

76.47% lines covered

17 relevant lines. 13 lines covered and 4 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require File.join(Gem::Specification.find_by_name("hyrax").full_gem_path, "app/presenters/hyrax/work_show_presenter.rb")
  3. # monkey patch Hyrax::WorkShowPresenter
  4. 1 module Hyrax
  5. 1 class WorkShowPresenter
  6. 1 def relative_url_root
  7. 1 rv = ::DeepBlueDocs::Application.config.relative_url_root
  8. 1 return rv if rv
  9. 1 ''
  10. end
  11. 1 def page_title
  12. 1 part1 = human_readable_type
  13. 1 part1 = "Data Set" if part1 == "Work"
  14. 1 "#{part1} | #{title.first} | ID: #{id} | #{I18n.t('hyrax.product_name')}"
  15. end
  16. 1 def tombstone
  17. solr_value = @solr_document[Solrizer.solr_name('tombstone', :symbol)]
  18. return nil if solr_value.blank?
  19. solr_value.first
  20. end
  21. 1 def tombstone_enabled?
  22. true
  23. end
  24. end
  25. end

app/services/dataset/date_coverage_service.rb

96.15% lines covered

52 relevant lines. 50 lines covered and 2 lines missed.
    
  1. 1 require 'date'
  2. 1 require 'edtf'
  3. 1 module Dataset
  4. 1 class DateCoverageService
  5. # EDTF's notation for interval begin and end when unspecified.
  6. 1 EDTF_OPEN_BEGIN = :unknown
  7. 1 EDTF_OPEN_END = :open
  8. 1 class << self
  9. # Given a parameters hash with date coverage keys
  10. # Returns an EDTF Interval or nil.
  11. 1 def params_to_interval( params )
  12. 7 begin_date = make_begin_date(
  13. year: safe_to_i(params[:date_coverage_begin_year]),
  14. month: safe_to_i(params[:date_coverage_begin_month]),
  15. day: safe_to_i(params[:date_coverage_begin_day])
  16. )
  17. 7 end_date = make_end_date(
  18. year: safe_to_i(params[:date_coverage_end_year]),
  19. month: safe_to_i(params[:date_coverage_end_month]),
  20. day: safe_to_i(params[:date_coverage_end_day])
  21. )
  22. 7 interv = EDTF::Interval.new(begin_date, end_date)
  23. 7 interv unless interval_reversed?(interv) || interval_both_ends_open?(interv)
  24. end
  25. # Given an EDTF Interval
  26. # Returns a corresponding hash of parameters for an edit form.
  27. 1 def interval_to_params( interv )
  28. 3 return unless interv.is_a?(EDTF::Interval)
  29. 2 return if interval_reversed?(interv)
  30. 1 make_begin_params(interv.begin).merge(make_end_params(interv.end))
  31. end
  32. 1 private
  33. # Determines if an intervals endings are reverse. Specifically, where the begin
  34. # date is later that the end date. An interval with reversed starting and ending
  35. # dates will have from and to attributes, but begin and end will be nil
  36. # == Parameters:
  37. # interv::
  38. # [EDTF::Interval] The interval to be tested.
  39. # == Returns:
  40. # [Boolean] True if the interval boundaries were reversed
  41. 1 def interval_reversed?(interv)
  42. 9 return false if interv.from == EDTF_OPEN_BEGIN || interv.to == EDTF_OPEN_END
  43. 6 (interv.from && !interv.begin) && (interv.to && !interv.end)
  44. end
  45. 1 def interval_both_ends_open?(interv)
  46. 6 interv.from == EDTF_OPEN_BEGIN && interv.to == EDTF_OPEN_END
  47. end
  48. 1 def make_begin_params(date)
  49. 1 hsh = date_to_params date
  50. 1 {date_coverage_begin_year: hsh[:year],
  51. date_coverage_begin_month: hsh[:month],
  52. date_coverage_begin_day: hsh[:day]}
  53. end
  54. 1 def make_end_params( date )
  55. 1 hsh = date_to_params date
  56. 1 {date_coverage_end_year: hsh[:year],
  57. date_coverage_end_month: hsh[:month],
  58. date_coverage_end_day: hsh[:day]}
  59. end
  60. # Given edtf date
  61. # return hash with possible keys :year, :month, :day
  62. 1 def date_to_params( date )
  63. 2 return {} unless date
  64. 2 hsh = case date.precision
  65. when :year
  66. {year: date.year}
  67. when :month
  68. {year: date.year, month: date.month}
  69. when :day
  70. 2 {year: date.year, month: date.month, day: date.day}
  71. end
  72. 2 hsh[:year] = year_to_s hsh[:year]
  73. 8 hsh.each{|k,v| hsh[k] = v.to_s}
  74. end
  75. 1 def year_to_s(val)
  76. 2 str = val.abs.to_s.rjust(4,"0")
  77. 2 val < 0 ? "-" + str : str
  78. end
  79. # Given input
  80. # Return the corresponding integer or nil
  81. 1 def safe_to_i(input)
  82. 60 Integer(input,10) rescue nil
  83. end
  84. # Until 8601-2 gets finalized, edtf ranges do not accept :open for begin.
  85. 1 def make_begin_date(year: nil, month: nil, day: nil)
  86. 7 make_date(year: year, month: month, day: day) || EDTF_OPEN_BEGIN
  87. end
  88. 1 def make_end_date(year: nil, month: nil, day: nil)
  89. 7 make_date(year: year, month: month, day: day) || EDTF_OPEN_END
  90. end
  91. # Takes year, month, and day integers.
  92. # Returns edtf date or nil
  93. 1 def make_date(year: nil, month: nil, day: nil)
  94. 14 if year && month && day
  95. 6 Date.new(year,month,day).day_precision!
  96. 8 elsif year && month
  97. 2 Date.new(year,month).month_precision!
  98. 6 elsif year
  99. 2 Date.new(year).year_precision!
  100. end
  101. end
  102. end
  103. end
  104. end

app/services/deepblue/about_to_expire_embargoes_service.rb

100.0% lines covered

41 relevant lines. 41 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 require 'tasks/abstract_task'
  4. 1 require_relative '../../helpers/hyrax/embargo_helper'
  5. 1 class AboutToExpireEmbargoesService
  6. 1 include ::Hyrax::EmbargoHelper
  7. 1 def initialize( email_owner: true, expiration_lead_days: nil, skip_file_sets: true, test_mode: true, to_console: false, verbose: false )
  8. 12 LoggingHelper.bold_debug [ LoggingHelper.here,
  9. LoggingHelper.called_from,
  10. LoggingHelper.obj_class( 'class', self ),
  11. "email_owner=#{email_owner}",
  12. "expiration_lead_days=#{expiration_lead_days}",
  13. "skip_file_sets=#{skip_file_sets}",
  14. "test_mode=#{test_mode}",
  15. "to_console=#{to_console}",
  16. "verbose=#{verbose}",
  17. "" ]
  18. 12 @email_owner = email_owner
  19. 12 @expiration_lead_days = expiration_lead_days
  20. 12 @skip_file_sets = skip_file_sets
  21. 12 @test_mode = test_mode
  22. 12 @to_console = to_console
  23. 12 @verbose = verbose
  24. end
  25. 1 def run
  26. 3 LoggingHelper.bold_debug [ LoggingHelper.here,
  27. LoggingHelper.called_from,
  28. LoggingHelper.obj_class( 'class', self ),
  29. "@email_owner=#{@email_owner}",
  30. "@expiration_lead_days=#{@expiration_lead_days}",
  31. "@skip_file_sets=#{@skip_file_sets}",
  32. "@test_mode=#{@test_mode}",
  33. "@to_console=#{@to_console}",
  34. "@verbose=#{@verbose}",
  35. "" ]
  36. 3 @now = DateTime.now
  37. 3 @assets = Array( assets_under_embargo )
  38. 3 if @expiration_lead_days.blank?
  39. 1 about_to_expire_embargoes_for_lead_days( lead_days: 7 )
  40. 1 about_to_expire_embargoes_for_lead_days( lead_days: 1 )
  41. else
  42. 2 @expiration_lead_days = @expiration_lead_days.to_i
  43. 2 if 0 < @expiration_lead_days
  44. 1 about_to_expire_embargoes_for_lead_days( lead_days: @expiration_lead_days )
  45. else
  46. 1 about_to_expire_embargoes_for_lead_days( lead_days: 7 )
  47. 1 about_to_expire_embargoes_for_lead_days( lead_days: 1 )
  48. end
  49. end
  50. end
  51. 1 def about_to_expire_embargoes_for_lead_days( lead_days: )
  52. 5 run_msg "about_to_expire_embargoes_for_lead_days: lead_days=#{lead_days}"
  53. # puts "expiration lead days: #{lead_days}" if @test_mode
  54. 5 lead_date = @now.beginning_of_day + lead_days.days
  55. 5 lead_date = lead_date.strftime "%Y%m%d"
  56. 5 run_msg "lead_date=#{lead_date}"
  57. 5 @assets.each_with_index do |asset,i|
  58. 5 next if @skip_file_sets && "FileSet" == asset.model_name
  59. 4 embargo_release_date = asset_embargo_release_date( asset: asset )
  60. 4 embargo_release_date = embargo_release_date.beginning_of_day.strftime "%Y%m%d"
  61. 4 run_msg "#{asset.id} embargo_release_date=#{embargo_release_date}"
  62. 4 if embargo_release_date == lead_date
  63. 2 run_msg "about to call about_to_expire_embargo_email for asset #{asset.id}" if @test_mode
  64. about_to_expire_embargo_email( asset: asset,
  65. expiration_days: lead_days,
  66. email_owner: @email_owner,
  67. test_mode: @test_mode,
  68. 2 verbose: @verbose ) unless @test_mode
  69. end
  70. end
  71. end
  72. 1 def run_msg( msg )
  73. 2 LoggingHelper.debug msg
  74. 2 puts msg if @to_console
  75. end
  76. end
  77. end

app/services/deepblue/deactivate_expired_embargoes_service.rb

100.0% lines covered

25 relevant lines. 25 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 require 'tasks/abstract_task'
  4. 1 require_relative '../../helpers/hyrax/embargo_helper'
  5. 1 class DeactivateExpiredEmbargoesService
  6. 1 include ::Hyrax::EmbargoHelper
  7. 1 def initialize( email_owner: true, skip_file_sets: true, test_mode: true, to_console: false, verbose: false )
  8. 6 LoggingHelper.bold_debug [ LoggingHelper.here,
  9. LoggingHelper.called_from,
  10. LoggingHelper.obj_class( 'class', self ),
  11. "email_owner=#{email_owner}",
  12. "skip_file_sets=#{skip_file_sets}",
  13. "test_mode=#{test_mode}",
  14. "to_console=#{to_console}",
  15. "verbose=#{verbose}",
  16. "" ]
  17. 6 @email_owner = email_owner
  18. 6 @skip_file_sets = skip_file_sets
  19. 6 @test_mode = test_mode
  20. 6 @to_console = to_console
  21. 6 @verbose = verbose
  22. end
  23. 1 def run
  24. 3 LoggingHelper.bold_debug [ LoggingHelper.here,
  25. LoggingHelper.called_from,
  26. LoggingHelper.obj_class( 'class', self ),
  27. "@email_owner=#{@email_owner}",
  28. "@skip_file_sets=#{@skip_file_sets}",
  29. "@test_mode=#{@test_mode}",
  30. "" ]
  31. 3 @now = DateTime.now
  32. 3 @assets = Array( assets_with_expired_embargoes )
  33. 3 run_msg "The number of assets with expired embargoes is: #{@assets.size}" if @verbose
  34. # puts
  35. 3 @assets.each_with_index do |asset,i|
  36. 3 next if @skip_file_sets && "FileSet" == asset.model_name
  37. 2 run_msg "#{i} - #{asset.id}, #{asset.model_name}, #{asset.human_readable_type}, #{asset.solr_document.title} #{asset.embargo_release_date}, #{asset.visibility_after_embargo}" if @verbose
  38. 2 model = ::ActiveFedora::Base.find asset.id
  39. 2 deactivate_embargo( curation_concern: model,
  40. copy_visibility_to_files: true,
  41. current_user: Deepblue::ProvenanceHelper.system_as_current_user,
  42. email_owner: @email_owner,
  43. test_mode: @test_mode,
  44. verbose: @verbose )
  45. end
  46. end
  47. 1 def run_msg( msg )
  48. 2 LoggingHelper.debug msg
  49. 2 puts msg if @to_console
  50. end
  51. end
  52. end

app/services/deepblue/doi_minting_service.rb

72.06% lines covered

68 relevant lines. 49 lines covered and 19 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 class DoiMintingService
  4. 1 PUBLISHER = "Indiana University".freeze
  5. 1 RESOURCE_TYPE = "Dataset".freeze
  6. 1 attr :current_user, :work, :metadata
  7. 1 def self.mint_doi_for( work:, current_user: )
  8. Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  9. Deepblue::LoggingHelper.called_from,
  10. "work.id=#{work.id}" ]
  11. service = Deepblue::DoiMintingService.new( work: work, current_user: current_user )
  12. Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  13. Deepblue::LoggingHelper.called_from,
  14. "work.id=#{work.id}",
  15. "about to call service.run" ]
  16. service.run
  17. rescue Exception => e # rubocop:disable Lint/RescueException
  18. Rails.logger.debug "DoiMintingService.mint_doi_for( work id = #{work.id}, current_user = #{current_user} ) rescue exception -- Exception: #{e.class}: #{e.message} at #{e.backtrace[0]}"
  19. unless work.nil?
  20. work.reload # consider locking work
  21. work.doi = nil
  22. work.save
  23. work.reload
  24. work.doi
  25. end
  26. raise
  27. end
  28. 1 def initialize( work:, current_user: )
  29. 5 Rails.logger.debug "DoiMintingService.initalize( work id = #{work.id} )"
  30. 5 @work = work
  31. 5 @current_user = current_user
  32. 5 @metadata = generate_metadata
  33. end
  34. 1 def run
  35. 4 Rails.logger.debug "DoiMintingService.run( work id = #{work.id} )"
  36. 4 rv = doi_server_reachable?
  37. 4 Rails.logger.debug "DoiMintingService.run doi_server_reachable?=#{rv}"
  38. 4 return mint_doi_failed unless rv
  39. 3 work.reload # consider locking work
  40. 3 work.doi = mint_doi
  41. 3 work.save
  42. 3 work.reload
  43. 3 work.provenance_mint_doi( current_user: current_user, event_note: 'DoiMintingService' )
  44. 3 work.doi
  45. end
  46. 1 def self.print_ezid_config
  47. config = Ezid::Client.config
  48. puts "Ezid::Client.config.host = #{config.host}"
  49. puts "Ezid::Client.config.port = #{config.port}"
  50. puts "Ezid::Client.config.user = #{config.user}"
  51. puts "Ezid::Client.config.password = #{config.password}"
  52. puts "Ezid::Client.config.default_shoulder = #{config.default_shoulder}"
  53. end
  54. 1 def ezid_config
  55. 3 config = Ezid::Client.config
  56. 3 return [ "Ezid::Client.config.host = #{config.host}",
  57. "Ezid::Client.config.port = #{config.port}",
  58. "Ezid::Client.config.user = #{config.user}",
  59. # "Ezid::Client.config.password = #{config.password}",
  60. "Ezid::Client.config.default_shoulder = #{config.default_shoulder}" ]
  61. end
  62. 1 private
  63. # Any error raised during connection is considered false
  64. 1 def doi_server_reachable?
  65. Ezid::Client.new.server_status.up? rescue false
  66. end
  67. 1 def generate_metadata
  68. 5 Ezid::Metadata.new.tap do |md|
  69. 5 md.datacite_title = work.title.first
  70. 5 md.datacite_publisher = PUBLISHER
  71. 5 md.datacite_publicationyear = Date.today.year.to_s
  72. 5 md.datacite_resourcetype= RESOURCE_TYPE
  73. 5 md.datacite_creator=work.creator.join(';')
  74. 5 md.target = Rails.application.routes.url_helpers.hyrax_data_set_url(id: work.id)
  75. end
  76. end
  77. 1 def mint_doi
  78. # identifier = Ezid::Identifier.create(@metadata)
  79. 3 Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  80. Deepblue::LoggingHelper.called_from,
  81. "work.id=#{work.id}",
  82. "metadata=#{metadata}" ]
  83. # Rails.logger.debug "DoiMintingService.mint_doi( #{metadata} )"
  84. # msg = ezid_config.join("\n")
  85. # Rails.logger.debug msg
  86. 3 Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  87. Deepblue::LoggingHelper.called_from,
  88. "work.id=#{work.id}" ] + ezid_config
  89. 3 shoulder = Ezid::Client.config.default_shoulder
  90. 3 identifier = Ezid::Identifier.mint( shoulder, @metadata )
  91. 3 identifier.id
  92. end
  93. 1 def mint_doi_failed
  94. 1 Rails.logger.error "DoiMintingService.mint_doi_failed work id = #{work.id}"
  95. 1 work.reload # consider locking work
  96. 1 work.doi = nil
  97. 1 work.save
  98. 1 work.reload
  99. 1 work.doi
  100. end
  101. end
  102. end

app/services/deepblue/log_exporter.rb

79.07% lines covered

43 relevant lines. 34 lines covered and 9 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 require 'json'
  4. # rubocop:disable Metrics/ParameterLists
  5. 1 class LogExporter < LogReader
  6. 1 DEFAULT_PP_EXPORT = false
  7. 1 attr_accessor :output, :output_mode
  8. 1 attr_reader :lines_exported
  9. 1 attr_reader :output_close, :output_pathname
  10. 1 attr_accessor :pp_export
  11. 1 def initialize( filter: nil, input:, output:, options: {} )
  12. 9 super( filter: filter, input: input, options: options )
  13. 9 @output = output
  14. 9 @pp_export = option( key: 'pp_export', default_value: DEFAULT_PP_EXPORT )
  15. 9 puts "pp_export=#{pp_export}" if verbose
  16. end
  17. 1 def export_line( line, timestamp, event, event_note, class_name, id, raw_key_values )
  18. 2 if pp_export
  19. 1 pretty_print_line line, timestamp, event, event_note, class_name, id, raw_key_values
  20. else
  21. 1 @output.puts line
  22. end
  23. end
  24. 1 def pretty_print_line( line, timestamp, event, event_note, class_name, id, raw_key_values )
  25. 1 @output.puts "#{timestamp} #{event}/#{event_note}/#{class_name}/#{id}"
  26. 1 @output.puts JSON.pretty_generate( JSON.parse( raw_key_values ) )
  27. end
  28. 1 def output_mode
  29. 2 @output_mode ||= option( key: 'output_mode', default_value: 'w' )
  30. end
  31. 1 def run
  32. 1 @lines_exported = 0
  33. 1 log_open_output
  34. 1 readlines do |line, timestamp, event, event_note, class_name, id, raw_key_values|
  35. export_line line, timestamp, event, event_note, class_name, id, raw_key_values
  36. @lines_exported += 1
  37. end
  38. ensure
  39. 1 log_close_output
  40. end
  41. # rubocop:disable Rails/Output
  42. 1 def quick_report
  43. 1 super
  44. 1 puts "output_pathname: #{@output_pathname}"
  45. 1 puts "lines_exported: #{@lines_exported}"
  46. end
  47. # rubocop:enable Rails/Output
  48. 1 protected
  49. 1 def log_close_output
  50. return unless @output_close
  51. @output.flush unless @output.nil? # rubocop:disable Style/SafeNavigation
  52. @output.close unless @output.nil? # rubocop:disable Style/SafeNavigation
  53. end
  54. 1 def log_open_output
  55. # puts "@output=#{@output}"
  56. @output_pathname = Pathname.new @output if @output.is_a? String
  57. # puts "@output_pathname=#{@output_pathname}"
  58. @output_pathname = @output if @output.is_a? Pathname
  59. # puts "@output_pathname=#{@output_pathname}"
  60. # return if @output_pathname.blank? # TODO: why doesn't this work
  61. # puts "output_mode=#{output_mode}"
  62. @output = open( @output_pathname, output_mode )
  63. @output_close = true
  64. end
  65. end
  66. # rubocop:enable Metrics/ParameterLists
  67. end

app/services/deepblue/log_extracter.rb

42.86% lines covered

14 relevant lines. 6 lines covered and 8 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 class LogExtracter < LogReader
  4. 1 attr_reader :lines_extracted
  5. 1 def initialize( filter: nil, input:, extract_parsed_tuple: false, options: {} )
  6. super( filter: filter, input: input, options: options )
  7. @extract_parsed_tuple = extract_parsed_tuple
  8. @lines_extracted = []
  9. end
  10. 1 def extract_line( line, timestamp, event, event_note, class_name, id, raw_key_values )
  11. if @extract_parsed_tuple
  12. @lines_extracted << [line, timestamp, event, event_note, class_name, id, raw_key_values]
  13. else
  14. @lines_extracted << line
  15. end
  16. end
  17. 1 def run
  18. readlines do |line, timestamp, event, event_note, class_name, id, raw_key_values|
  19. extract_line line, timestamp, event, event_note, class_name, id, raw_key_values
  20. end
  21. end
  22. end
  23. end

app/services/deepblue/log_filter.rb

42.31% lines covered

208 relevant lines. 88 lines covered and 120 lines missed.
    
  1. # frozen_string_literal: true
  2. # rubocop:disable Metrics/ParameterLists
  3. 1 module Deepblue
  4. 1 class AbstractFilter
  5. 1 attr_accessor :verbose
  6. 1 def initialize( options: {} )
  7. 9 @verbose = options_value( options, key: "verbose_filters", default_value: false )
  8. # ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  9. # ::Deepblue::LoggingHelper.called_from,
  10. # "verbose=#{verbose}",
  11. # "" ]
  12. # puts "#{::Deepblue::LoggingHelper.here} self.class.name=#{self.class.name}"
  13. # puts "#{::Deepblue::LoggingHelper.here} options=#{options}"
  14. # puts "#{::Deepblue::LoggingHelper.here} verbose=#{verbose}"
  15. end
  16. 1 protected
  17. 1 def options_value( options, key:, default_value: nil, verbose: false )
  18. 9 return default_value if options.blank?
  19. return default_value unless options.key? key
  20. puts "set key #{key} to #{options[key]}" if verbose
  21. return options[key]
  22. end
  23. end
  24. 1 class AbstractArrayOfFilters < AbstractFilter
  25. 1 attr_reader :filters
  26. 1 def initialize( filters: [], options: {} )
  27. super( options: options )
  28. @filters = Array( filters )
  29. end
  30. 1 def add_filters( new_filters:, append: true )
  31. new_filters = Array( new_filters )
  32. if append
  33. @filters.concat new_filters
  34. else
  35. until new_filters.empty?
  36. filter = new_filters.pop
  37. @filters.unshift filter
  38. end
  39. end
  40. return self
  41. end
  42. 1 def all_log_filter?
  43. false
  44. end
  45. end
  46. 1 class AndLogFilter < AbstractArrayOfFilters
  47. 1 def initialize( filters: [], options: {} )
  48. super( filters: filters, options: options )
  49. end
  50. 1 def and( new_filters: )
  51. add_filters( new_filters: new_filters )
  52. end
  53. 1 def or( new_filters: )
  54. new_filter = OrLogFilter.new( filters: self ).add_filters( new_filters: new_filters )
  55. return new_filter
  56. end
  57. 1 def filter_in( timestamp, event, event_note, class_name, id, raw_key_values )
  58. filters.each do |filter|
  59. return false unless filter.filter_in( timestamp, event, event_note, class_name, id, raw_key_values )
  60. end
  61. return true
  62. end
  63. end
  64. 1 class OrLogFilter < AbstractArrayOfFilters
  65. 1 def initialize( filters: [], options: {} )
  66. super( filters: filters, options: options )
  67. end
  68. 1 def and( new_filters: )
  69. new_filter = AndLogFilter.new( filters: self ).add_filters( new_filters: new_filters )
  70. return new_filter
  71. end
  72. 1 def or( new_filters: )
  73. add_filters( new_filters: new_filters )
  74. end
  75. 1 def filter_in( timestamp, event, event_note, class_name, id, raw_key_values )
  76. filters.each do |filter|
  77. return true if filter.filter_in( timestamp, event, event_note, class_name, id, raw_key_values )
  78. end
  79. return false
  80. end
  81. end
  82. 1 class AbstractLogFilter < AbstractFilter
  83. 1 def initializer( options: {} )
  84. super( options: options )
  85. end
  86. 1 def all_log_filter?
  87. false
  88. end
  89. 1 def and( new_filters: )
  90. new_filter = AndLogFilter.new( filters: self ).add_filters( new_filters: new_filters )
  91. return new_filter
  92. end
  93. 1 def or( new_filters: )
  94. new_filter = OrLogFilter.new( filters: self ).add_filters( new_filters: new_filters )
  95. return new_filter
  96. end
  97. 1 def filter_in( _timestamp, _event, _event_note, _class_name, _id, _raw_key_values )
  98. puts "#{::Deepblue::LoggingHelper.here} filter_in returning false"
  99. false
  100. end
  101. 1 protected
  102. 1 def arg_to_array( arg )
  103. arr = if arg.is_a? String
  104. arg.split( ' ' )
  105. else
  106. Array( arg )
  107. end
  108. return arr
  109. end
  110. 1 def arg_to_timestamp( arg, timestamp_format: )
  111. timestamp = arg
  112. if timestamp_format.blank?
  113. return DateTime.strptime( arg, "%Y-%m-%d %H:%M:%S" ) if arg.match?( /\d\d\d\d\-\d\d?\-\d\d? \d\d?:\d\d:\d\d/ )
  114. return DateTime.strptime( arg, "%m/%d/%Y" ) if arg.match?( /\d\d?\/\d\d?\/\d\d\d\d/ )
  115. return DateTime.strptime( arg, "%m-%d-%Y" ) if arg.match?( /\d\d?\-\d\d?\-\d\d\d\d/ )
  116. return DateTime.strptime( arg, "%Y" ) if arg.match?( /\d\d\d\d/ )
  117. timestamp = DateTime.parse( arg ) if arg.is_a? String
  118. elsif arg.is_a? String
  119. timestamp = DateTime.strptime( arg, timestamp_format )
  120. end
  121. return timestamp
  122. rescue ArgumentError
  123. puts "DateTime.parse failed - arg='#{arg}' timestamp_format='#{timestamp_format}'" # - #{e.class}: #{e.message} at #{e.backtrace[0]}"
  124. end
  125. 1 def parse_key_values( raw_key_values )
  126. ProvenanceHelper.parse_log_line_key_values raw_key_values
  127. end
  128. end
  129. 1 class NotLogFilter < AbstractLogFilter
  130. 1 attr_reader :filter
  131. 1 def initialize( filter:, options: {} )
  132. super( options: options )
  133. @filter = filter
  134. end
  135. 1 def filter_in( timestamp, event, event_note, class_name, id, raw_key_values )
  136. rv = @filter.filter_in( timestamp, event, event_note, class_name, id, raw_key_values )
  137. return !rv
  138. end
  139. end
  140. 1 class AllLogFilter < AbstractLogFilter
  141. 1 def initialize( options: {} )
  142. 9 super( options: options )
  143. end
  144. 1 def all_log_filter?
  145. true
  146. end
  147. 1 def filter_in( _timestamp, _event, _event_note, _class_name, _id, _raw_key_values )
  148. true
  149. end
  150. end
  151. 1 class ClassNameLogFilter < AbstractLogFilter
  152. 1 attr_reader :matching_class_names
  153. 1 def initialize( matching_class_names: [], options: {} )
  154. super( options: options )
  155. @matching_classe_names = arg_to_array matching_class_names
  156. end
  157. 1 def filter_in( _timestamp, _event, _event_note, class_name, _id, _raw_key_values )
  158. puts "#{@matching_classe_names} include? #{class_name}" if verbose
  159. @matching_classe_names.include? class_name
  160. end
  161. end
  162. 1 class CollectionLogFilter < ClassNameLogFilter
  163. 1 def initialize( options: {} )
  164. super( matching_class_names: [ Collection.name ], options: options )
  165. end
  166. end
  167. 1 class DataSetLogFilter < ClassNameLogFilter
  168. 1 def initialize( options: {} )
  169. super( matching_class_names: [ DataSet.name ], options: options )
  170. end
  171. end
  172. 1 class DateLogFilter < AbstractLogFilter
  173. 1 attr_reader :begin_timestamp, :end_timestamp
  174. # Examples:
  175. #
  176. # filter = Deepblue::DataLogFilter.new( begin_timestamp: Date.new=( 2018, 08, 17 ) )
  177. # filter = Deepblue::DataLogFilter.new( begin_timestamp: DateTime.new( 2018, 08, 17, 10, 0, 0 ) )
  178. # filter = Deepblue::DataLogFilter.new( begin_timestamp: DateTime.now - 3.days )
  179. #
  180. # filter = Deepblue::DataLogFilter.new( begin_timestamp: '2018/08/17', timestamp_format: '%Y/%m/%d' )
  181. # filter = Deepblue::DataLogFilter.new( begin_timestamp: '2018/08/17 12:10:00', timestamp_format: '%Y/%m/%d %H:%M:%S' )
  182. #
  183. # filter = Deepblue::DateLogFilter.new( begin_timestamp: "2018-08-16 15:00:00", timestamp_format: '%Y-%m-%d %H:%M:%S' )
  184. #
  185. # filter = Deepblue::DateLogFilter.new( begin_timestamp: Date.new - 2.days )
  186. #
  187. 1 def initialize( begin_timestamp: nil, end_timestamp: nil, timestamp_format: '', options: {} )
  188. super( options: options )
  189. @begin_timestamp = arg_to_timestamp( begin_timestamp, timestamp_format: timestamp_format )
  190. @end_timestamp = arg_to_timestamp( end_timestamp, timestamp_format: timestamp_format )
  191. end
  192. 1 def filter_in( timestamp, _event, _event_note, _class_name, _id, _raw_key_values )
  193. before_begin = false
  194. before_begin = timestamp < @begin_timestamp if @begin_timestamp.present?
  195. after_end = false
  196. after_end = timestamp > @after_timestamp if @after_timestamp.present?
  197. puts "#{::Deepblue::LoggingHelper.here} filter_in returning..."
  198. puts "#{timestamp} is before_begin? #{before_begin} and #{timestamp} is after_end? #{after_end}"
  199. return !before_begin && !after_end
  200. end
  201. 1 def begin_timestamp_label
  202. ts = begin_timestamp
  203. return '' if ts.blank?
  204. ts.strftime "%Y%m%d%H%M%S"
  205. end
  206. 1 def end_timestamp_label
  207. ts = end_timestamp
  208. return '' if ts.blank?
  209. ts.strftime "%Y%m%d%H%M%S"
  210. end
  211. 1 def date_range_label
  212. ts1 = begin_timestamp_label
  213. ts2 = end_timestamp_label
  214. return '' if ts1.blank? && ts2.blank?
  215. return ts1 if ts2.blank?
  216. return ts2 if ts1.blank?
  217. return "#{ts1}-#{ts2}"
  218. end
  219. end
  220. 1 class EventLogFilter < AbstractLogFilter
  221. 1 attr_reader :matching_events
  222. 1 def initialize( matching_events: [], options: {} )
  223. super( options: options )
  224. @matching_events = arg_to_array matching_events
  225. end
  226. 1 def filter_in( _timestamp, event, _event_note, _class_name, _id, _raw_key_values )
  227. puts "#{@matching_events} include? #{event}" if verbose
  228. @matching_events.include? event
  229. end
  230. end
  231. 1 class CreateOrDestroyLogFilter < EventLogFilter
  232. 1 def initialize( options: {} )
  233. super( matching_events: [ AbstractEventBehavior::EVENT_CREATE, AbstractEventBehavior::EVENT_DESTROY ],
  234. options: options )
  235. end
  236. end
  237. 1 class FileSetFilter < ClassNameLogFilter
  238. 1 def initialize( options: {} )
  239. super( matching_class_names: [ FileSet.name ], options: options )
  240. end
  241. end
  242. 1 class FixityCheckLogFilter < EventLogFilter
  243. 1 def initialize( options: {} )
  244. super( matching_events: [ AbstractEventBehavior::EVENT_FIXITY_CHECK ], options: options )
  245. end
  246. end
  247. 1 class MigrationEventFilter < EventLogFilter
  248. 1 def initialize( options: {} )
  249. super( matching_events: [ AbstractEventBehavior::EVENT_CHILD_ADD,
  250. AbstractEventBehavior::EVENT_FIXITY_CHECK,
  251. AbstractEventBehavior::EVENT_INGEST,
  252. AbstractEventBehavior::EVENT_MIGRATE,
  253. AbstractEventBehavior::EVENT_VIRUS_SCAN ],
  254. options: options )
  255. end
  256. end
  257. 1 class IdLogFilter < AbstractLogFilter
  258. 1 attr_reader :matching_ids
  259. 1 def initialize( matching_ids: [], options: {} )
  260. super( options: options )
  261. @matching_ids = arg_to_array matching_ids
  262. end
  263. 1 def filter_in( _timestamp, _event, _event_note, _class_name, id, _raw_key_values )
  264. @matching_ids.include? id
  265. end
  266. 1 def filter_in_child_id( raw_key_values )
  267. key_values = parse_key_values raw_key_values
  268. child_id = key_values['child_id']
  269. return false if child_id.blank?
  270. @matching_ids.include? child_id
  271. end
  272. 1 def filter_in_parent_id( raw_key_values )
  273. key_values = parse_key_values raw_key_values
  274. parent_id = key_values['parent_id']
  275. return false if parent_id.blank?
  276. @matching_ids.include? parent_id
  277. end
  278. 1 def filter_in_parent_or_child_id( raw_key_values )
  279. key_values = parse_key_values raw_key_values
  280. id = key_values['parent_id']
  281. return true if id.present? && @matching_ids.include?( id )
  282. id = key_values['child_id']
  283. return false if id.blank?
  284. @matching_ids.include? id
  285. end
  286. end
  287. 1 class ChildIdLogFilter < IdLogFilter
  288. 1 def initialize( matching_ids: [], options: {} )
  289. super( matching_ids: matching_ids, options: options )
  290. end
  291. 1 def filter_in( _timestamp, _event, _event_note, _class_name, _id, raw_key_values )
  292. filter_in_child_id raw_key_values
  293. end
  294. end
  295. 1 class IdOrParentIdLogFilter < IdLogFilter
  296. 1 def initialize( matching_ids: [], options: {} )
  297. super( matching_ids: matching_ids , options: options)
  298. end
  299. 1 def filter_in( timestamp, event, event_note, class_name, id, raw_key_values )
  300. return true if super.filter_in( timestamp, event, event_note, class_name, id, raw_key_values )
  301. filter_in_parent_id raw_key_values
  302. end
  303. end
  304. 1 class IdOrParentOrChildIdLogFilter < IdLogFilter
  305. 1 def initialize( matching_ids: [], options: {} )
  306. super( matching_ids: matching_ids, options: options )
  307. end
  308. 1 def filter_in( timestamp, event, event_note, class_name, id, raw_key_values )
  309. return true if super.filter_in( timestamp, event, event_note, class_name, id, raw_key_values )
  310. filter_in_parent_or_child_id raw_key_values
  311. end
  312. end
  313. 1 class ParentIdLogFilter < IdLogFilter
  314. 1 def initialize( matching_ids: [], options: {} )
  315. super( matching_ids: matching_ids, options: options )
  316. end
  317. 1 def filter_in( _timestamp, _event, _event_note, _class_name, _id, raw_key_values )
  318. filter_in_parent_id raw_key_values
  319. end
  320. end
  321. end
  322. # rubocop:enable Metrics/ParameterLists

app/services/deepblue/log_reader.rb

76.86% lines covered

121 relevant lines. 93 lines covered and 28 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 require_relative './log_filter'
  4. 1 class LogReader
  5. 1 DEFAULT_BEGIN_TIMESTAMP = ''
  6. 1 DEFAULT_END_TIMESTAMP = ''
  7. 1 DEFAULT_TIMESTAMP_FORMAT = ''
  8. 1 DEFAULT_VERBOSE = false
  9. 1 DEFAULT_VERBOSE_FILTER = false
  10. 1 attr_accessor :verbose, :verbose_filter
  11. 1 attr_reader :current_line
  12. 1 attr_reader :date_range_filter
  13. 1 attr_reader :filter # , :filter_predicate
  14. 1 attr_reader :input, :input_pathname, :input_mode, :input_close
  15. 1 attr_reader :lines_parsed, :lines_read
  16. 1 attr_reader :options
  17. 1 attr_reader :parsed,
  18. :parsed_timestamp,
  19. :parsed_event,
  20. :parsed_event_note,
  21. :parsed_class_name,
  22. :parsed_id,
  23. :parsed_raw_key_values
  24. # filter_predicate: ->( _timestamp, _event, _event_note, _class_name, _id, _key_values ) { true },
  25. 1 def initialize( filter: nil,
  26. input:,
  27. options: {} )
  28. 34 @filter = initialize_filter filter
  29. # @filter_predicate = filter_predicate
  30. 34 @input = input
  31. 34 @options = options
  32. 34 @verbose = option( key: 'verbose', default_value: DEFAULT_VERBOSE )
  33. 34 @verbose_filter = option( key: 'verbose_filter', default_value: DEFAULT_VERBOSE_FILTER )
  34. 34 add_date_range_filter
  35. end
  36. 1 def initialize_filter( filter, options: {} )
  37. 37 return AllLogFilter.new if filter.blank?
  38. 27 return AndLogFilter.new( filters: filter, options: options ) if filter.is_a? Array
  39. 26 filter
  40. end
  41. 1 def add_date_range_filter( options: {} )
  42. 36 begin_timestamp = option( key: 'begin' )
  43. 36 begin_timestamp = option( key: 'begin_timestamp', default_value: DEFAULT_BEGIN_TIMESTAMP ) unless begin_timestamp.present?
  44. 36 end_timestamp = option( key: 'end' )
  45. 36 end_timestamp = option( key: 'end_timestamp', default_value: DEFAULT_END_TIMESTAMP ) unless end_timestamp.present?
  46. 36 timestamp_format = option( key: 'format' )
  47. 36 timestamp_format = option( key: 'timestamp_format', default_value: DEFAULT_TIMESTAMP_FORMAT ) unless timestamp_format.present?
  48. 36 puts "add_date_range_filter begin_timestamp=#{begin_timestamp} end_timestamp=#{end_timestamp}" if verbose_filter # rubocop:disable Rails/Output
  49. 36 return if begin_timestamp.blank? && end_timestamp.blank?
  50. 1 @date_range_filter = DateLogFilter.new( begin_timestamp: begin_timestamp,
  51. end_timestamp: end_timestamp,
  52. timestamp_format: timestamp_format,
  53. options: options )
  54. 1 filter_and( new_filters: date_range_filter )
  55. end
  56. 1 def filter_and( new_filters:, append: true, options: {} )
  57. 2 return if new_filters.blank?
  58. 1 current_filter = @filter
  59. 1 @filter = filter_refresh current_filter: current_filter, new_filters: new_filters, append: append, options: options
  60. 1 puts "filter_and @filter=#{@filter}" if verbose # rubocop:disable Rails/Output
  61. end
  62. 1 def filter_refresh( current_filter:, new_filters:, append: true, options: {} )
  63. 4 if current_filter.all_log_filter?
  64. 2 if new_filters.is_a? Array
  65. 1 AndLogFilter.new( filters: new_filters, options: options )
  66. else
  67. 1 new_filters
  68. end
  69. 2 elsif append
  70. 1 current_filter.and( new_filters: new_filters )
  71. else
  72. 1 new_filters = Array( new_filters )
  73. 1 new_filters.concat current_filter
  74. 1 AndLogFilter.new( filters: new_filters, options: options )
  75. end
  76. end
  77. 1 def filter_or( new_filters:, append: true, options: {} )
  78. 4 return if new_filters.blank?
  79. 3 current_filter = @filter
  80. 3 @filter = if append && current_filter.all_log_filter?
  81. 1 current_filter # new_filters are unreachable, so ignore
  82. 2 elsif append
  83. 1 current_filter.or( new_filters: new_filters )
  84. else
  85. 1 new_filters = Array( new_filters )
  86. 1 new_filters.concat current_filter
  87. 1 OrLogFilter.new( filters: new_filters, options: options )
  88. end
  89. end
  90. 1 def input_mode
  91. 1 @input_mode ||= option( key: 'input_mode', default_value: 'r' )
  92. end
  93. 1 def parse_line
  94. # line is of the form: "timestamp event/event_note/class_name/id key_values"
  95. 3 @parsed_timestamp = nil
  96. 3 @parsed_event = nil
  97. 3 @parsed_event_note = nil
  98. 3 @parsed_class_name = nil
  99. 3 @parsed_id = nil
  100. 3 @parsed_raw_key_values = nil
  101. 3 @parsed = false
  102. 3 return if @current_line.blank?
  103. @parsed_timestamp,
  104. @parsed_event,
  105. @parsed_event_note,
  106. @parsed_class_name,
  107. @parsed_id,
  108. 2 @parsed_raw_key_values = ProvenanceHelper.parse_log_line( @current_line,
  109. line_number: @lines_read,
  110. raw_key_values: true )
  111. 1 @lines_parsed += 1
  112. 1 @parsed = true
  113. rescue LogParseError => e
  114. 1 puts e.message # rubocop:disable Rails/Output
  115. end
  116. # rubocop:disable Rails/Output
  117. 1 def quick_report
  118. 2 puts
  119. 2 puts "Quick report"
  120. 2 puts "input_pathname: #{input_pathname}"
  121. 2 puts "lines_read: #{lines_read}"
  122. 2 puts "lines_parsed: #{lines_parsed}"
  123. end
  124. # rubocop:enable Rails/Output
  125. 1 def readlines( &for_filtered_line_block )
  126. @lines_parsed = 0
  127. @lines_read = 0
  128. log_open_input
  129. # for each line of input
  130. @current_line = nil
  131. line_filter = filter
  132. until @input.eof?
  133. @current_line = @input.readline
  134. @current_line.chop!
  135. @lines_read += 1
  136. parse_line
  137. next unless @parsed
  138. # next @filter_predicate.call( @parsed_timestamp,
  139. next unless line_filter.filter_in( @parsed_timestamp,
  140. @parsed_event,
  141. @parsed_event_note,
  142. @parsed_class_name,
  143. @parsed_id,
  144. @parsed_raw_key_values )
  145. next unless for_filtered_line_block
  146. yield( @current_line,
  147. @parsed_timestamp,
  148. @parsed_event,
  149. @parsed_event_note,
  150. @parsed_class_name,
  151. @parsed_id,
  152. @parsed_raw_key_values )
  153. end
  154. ensure
  155. log_close_input
  156. end
  157. 1 protected
  158. 1 def log_close_input
  159. return unless @input_close
  160. @input.close unless @input.nil? # rubocop:disable Style/SafeNavigation
  161. end
  162. 1 def log_open_input
  163. @input_pathname = Pathname.new @input if @input.is_a? String
  164. @input_pathname = @input if @input.is_a? Pathname
  165. return unless @input_pathname.exist?
  166. @input = open( @input_pathname, 'r' )
  167. @input_close = true
  168. end
  169. 1 def option( key:, default_value: nil )
  170. 281 return default_value unless options_key? key
  171. return @options[key] if @options.key? key
  172. return @options[key.to_sym] if key.is_a? String
  173. return @options[key.to_s] if key.is_a? Symbol
  174. return default_value
  175. end
  176. 1 def options_key?( key )
  177. 281 return true if @options.key? key
  178. 281 return @options.key? key.to_sym if key.is_a? String
  179. return @options.key? key.to_s if key.is_a? Symbol
  180. return false
  181. end
  182. end
  183. end

app/services/deepblue/log_reporter.rb

65.12% lines covered

43 relevant lines. 28 lines covered and 15 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 require_relative './log_reader'
  4. # rubocop:disable Metrics/ParameterLists
  5. 1 class LogReporter < LogReader
  6. 1 attr_reader :lines_reported
  7. 1 attr_reader :output, :output_close, :output_mode, :output_pathname
  8. 1 attr_reader :timestamp_first, :timestamp_last
  9. 1 attr_reader :class_events
  10. 1 attr_reader :events
  11. 1 attr_reader :ids
  12. 1 def initialize( filter: nil, input:, options: {} )
  13. 4 super( filter: filter, input: input, options: options )
  14. 4 @output_close = false
  15. 4 @output_mode = 'w'
  16. 4 @output_pathname = nil
  17. end
  18. # rubocop:disable Rails/Output
  19. 1 def report
  20. 1 run
  21. # TODO: pretty output
  22. 1 puts "timestamp_first = #{@timestamp_first}"
  23. 1 puts "timestamp_last = #{@timestamp_last}"
  24. 1 puts "ids = #{ids}"
  25. 1 puts "events = #{events}"
  26. 1 puts "class_events = #{class_events}"
  27. end
  28. # rubocop:enable Rails/Output
  29. 1 def run
  30. 1 initialize_report_values
  31. 1 readlines do |line, timestamp, event, event_note, class_name, id, raw_key_values|
  32. line_read( line, timestamp, event, event_note, class_name, id, raw_key_values )
  33. end
  34. end
  35. 1 protected
  36. 1 def class_event_key( class_name:, event: )
  37. "#{class_name}_#{event}"
  38. end
  39. 1 def initialize_report_values
  40. @lines_reported = 0
  41. @timestamp_first = nil
  42. @timestamp_last = nil
  43. @events = Hash.new { |h, k| h[k] = 0 }
  44. @class_events = Hash.new { |h, k| h[k] = 0 }
  45. @ids = {}
  46. end
  47. 1 def line_read( _line, timestamp, event, _event_note, class_name, id, _raw_key_values )
  48. @lines_reported += 1
  49. @timestamp_first = timestamp if @timestamp_first.blank?
  50. @timestamp_last = timestamp
  51. @ids[id] = true unless @ids.key? id
  52. @events[event] = @events[event] + 1
  53. class_event_key = class_event_key( class_name: class_name, event: event )
  54. @class_events[class_event_key] = @class_events[class_event_key] + 1
  55. end
  56. end
  57. # rubocop:enable Metrics/ParameterLists
  58. end

app/services/deepblue/logging_callback.rb

100.0% lines covered

27 relevant lines. 27 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 class LoggingCallback
  4. 1 def self.process_event( event_name:, msg: )
  5. 1 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  6. 1 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  7. 1 Rails.logger.debug "#{event_name} >>>>> #{msg}"
  8. 1 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  9. 1 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  10. end
  11. 1 def self.process_event_curation_concern( event_name:, curation_concern:, user: )
  12. 3 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  13. 3 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  14. 3 Rails.logger.debug "#{event_name} >>>>> #{user} >>>>> #{curation_concern}"
  15. 3 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  16. 3 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  17. end
  18. 1 def self.process_event_file_set( event_name:, file_set:, user: )
  19. 3 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  20. 3 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  21. 3 Rails.logger.debug "#{event_name} >>>>> #{user} >>>>> #{file_set}"
  22. 3 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  23. 3 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  24. end
  25. 1 def self.process_event_user( event_name:, user:, msg: '' )
  26. 5 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  27. 5 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  28. 5 Rails.logger.debug "#{event_name} >>>>> #{user}" if msg.blank?
  29. 5 Rails.logger.debug "#{event_name} >>>>> #{user} >>>>> #{msg}" if msg.present?
  30. 5 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  31. 5 Rails.logger.debug ">>>>> #{event_name} >>>>>"
  32. end
  33. end
  34. end

app/services/deepblue/logging_service.rb

53.85% lines covered

13 relevant lines. 7 lines covered and 6 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 class LoggingService
  4. 1 attr_reader :event_name
  5. 1 def initialize( event_name: )
  6. 11 @event_name = event_name
  7. 11 ActiveSupport::Notifications.subscribe @event_name do |*args|
  8. process_event( *args )
  9. end
  10. end
  11. 1 def process_event( *args )
  12. Rails.logger.debug ">>>>> #{@event_name} >>>>>"
  13. Rails.logger.debug ">>>>> #{@event_name} >>>>>"
  14. Rails.logger.debug "#{@event_name} >>>>> #{args.extract_options!}"
  15. Rails.logger.debug ">>>>> #{@event_name} >>>>>"
  16. Rails.logger.debug ">>>>> #{@event_name} >>>>>"
  17. end
  18. end
  19. end

app/services/deepblue/provenance_log_service.rb

21.21% lines covered

66 relevant lines. 14 lines covered and 52 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 require 'json'
  4. 1 require_relative './log_extracter'
  5. 1 require_relative './log_filter'
  6. 1 class ProvenanceLogService
  7. 1 def self.provenance_log_name
  8. DeepBlueDocs::Application.config.provenance_log_name
  9. end
  10. 1 def self.provenance_log_path
  11. DeepBlueDocs::Application.config.provenance_log_path
  12. end
  13. 1 def self.entries( id, refresh: false )
  14. Deepblue::LoggingHelper.bold_debug "ProvenanceLogService.entries( #{id}, #{refresh} )"
  15. file_path = Deepblue::ProvenancePath.path_for_reference( id )
  16. if !refresh && File.exist?( file_path )
  17. rv = read_entries( file_path )
  18. else
  19. rv = filter_entries( id )
  20. write_entries( file_path, rv )
  21. end
  22. Deepblue::LoggingHelper.bold_debug "ProvenanceLogService.entries( #{id} ) read #{rv.size} entries"
  23. return rv
  24. end
  25. 1 def self.filter_entries( id )
  26. input = Rails.root.join( 'log', "provenance_#{Rails.env}.log" )
  27. filter = Deepblue::IdLogFilter.new( matching_ids: Array( id ) )
  28. extractor = Deepblue::LogExtracter.new( filter: filter, input: input )
  29. extractor.run
  30. rv = extractor.lines_extracted
  31. return rv
  32. end
  33. 1 def self.parse_entry( entry, line_number: 0 )
  34. # line is of the form: "timestamp event/event_note/class_name/id key_values"
  35. timestamp = nil
  36. event = nil
  37. event_note = nil
  38. class_name = nil
  39. id = nil
  40. raw_key_values = nil
  41. timestamp, event, event_note, class_name, id,
  42. raw_key_values = ProvenanceHelper.parse_log_line( entry, line_number: line_number, raw_key_values: true )
  43. return { timestamp: timestamp, event: event, event_note: event_note, class_name: class_name, id: id,
  44. raw_key_values: raw_key_values, line_number: line_number, parse_error: nil }
  45. rescue LogParseError => e
  46. return { entry: entry, line_number: line_number, parse_error: e }
  47. end
  48. 1 def self.pp_key_values( raw_key_values )
  49. return JSON.pretty_generate( JSON.parse( raw_key_values ) )
  50. end
  51. 1 def self.key_values_to_table( key_values, parse: false )
  52. key_values = JSON.parse( key_values ) if parse
  53. if key_values.is_a? Array
  54. case key_values.size
  55. when 0 then return "<table>\n<tr><td>&nbsp;</td></tr>\n</table>\n"
  56. when 1 then return "<table>\n<tr><td>#{ERB::Util.html_escape( key_values[0] )}</td></tr>\n</table>\n"
  57. else
  58. arr = key_values.map { |x| key_values_to_table( x ) }
  59. return "<table>\n<tr><td>#{arr.join("</td></tr>\n<tr><td>")}</td></tr>\n</table>\n"
  60. end
  61. elsif key_values.is_a? Hash
  62. rv = "<table>\n"
  63. key_values.each_pair do |key,value|
  64. rv += "<tr><td>#{ERB::Util.html_escape( key )}</td><td>#{key_values_to_table( value )}</td></tr>\n"
  65. end
  66. rv += "</table>\n"
  67. return rv
  68. else
  69. return ERB::Util.html_escape( key_values )
  70. end
  71. end
  72. 1 def self.read_entries( file_path )
  73. entries = []
  74. open( file_path, "r" ) do |fin|
  75. until fin.eof?
  76. begin
  77. line = fin.readline
  78. line.chop!
  79. entries << line
  80. rescue EOFError
  81. line = nil
  82. end
  83. end
  84. end
  85. return entries
  86. end
  87. 1 def self.write_entries( file_path, entries )
  88. # file_path = Pathname.new file_path unless file_path.is_a? Pathname
  89. dir = File.dirname file_path
  90. FileUtils.mkpath dir unless Dir.exist? dir
  91. File.open( file_path, "w" ) do |out|
  92. entries.each { |line| out.puts line }
  93. end
  94. end
  95. end
  96. end

app/services/deepblue/provenance_path.rb

56.52% lines covered

23 relevant lines. 13 lines covered and 10 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 class ProvenancePath
  4. 1 attr_reader :id, :destination_name
  5. 1 class << self
  6. # Path on file system where derivative file is stored
  7. # @param [ActiveFedora::Base or String] object either the AF object or its id
  8. 1 def path_for_reference( object )
  9. new( object, "provenance" ).provenance_path
  10. end
  11. # # @param [ActiveFedora::Base or String] object either the AF object or its id
  12. # # @return [Array<String>] Array of paths to derivatives for this object.
  13. # def derivatives_for_reference(object)
  14. # new(object).all_paths
  15. # end
  16. end
  17. # @param [ActiveFedora::Base, String] object either the AF object or its id
  18. 1 def initialize( object, destination_name = nil )
  19. @id = object.is_a?(String) ? object : object.id
  20. @destination_name = destination_name
  21. end
  22. 1 def provenance_path
  23. "#{path_prefix}-#{file_name}" # TODO
  24. end
  25. # def all_paths
  26. # Dir.glob(root_path.join("*")).select do |path|
  27. # path.start_with?(path_prefix.to_s)
  28. # end
  29. # end
  30. 1 private
  31. # @return [String] Returns the root path where derivatives will be generated into.
  32. 1 def root_path
  33. Pathname.new( provenance_path ).dirname
  34. end
  35. # @return <Pathname> Full prefix of the path for object.
  36. 1 def path_prefix
  37. Pathname.new( Hyrax.config.derivatives_path ).join( pair_path ) # TODO
  38. end
  39. 1 def pair_path
  40. id.split('').each_slice(2).map(&:join).join('/')
  41. end
  42. 1 def file_name
  43. return unless destination_name
  44. destination_name + extension
  45. end
  46. 1 def extension
  47. ".log"
  48. end
  49. end
  50. end

app/services/deepblue/virus_scan_service.rb

100.0% lines covered

18 relevant lines. 18 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 module VirusScanService
  4. 1 VIRUS_SCAN_ERROR = 'scan error'
  5. 1 VIRUS_SCAN_NOT_VIRUS = 'not virus'
  6. 1 VIRUS_SCAN_SKIPPED = 'scan skipped'
  7. 1 VIRUS_SCAN_SKIPPED_SERVICE_UNAVAILABLE = 'scan skipped service unavailable'
  8. 1 VIRUS_SCAN_SKIPPED_TOO_BIG = 'scan skipped too big'
  9. 1 VIRUS_SCAN_UNKNOWN = 'scan unknown'
  10. 1 VIRUS_SCAN_VIRUS = 'virus'
  11. 1 def virus_scan_detected_virus?( scan_result: )
  12. 2 VIRUS_SCAN_VIRUS == scan_result
  13. end
  14. 1 def virus_scan_service_name
  15. 1 Hydra::Works.default_system_virus_scanner.name
  16. end
  17. 1 def virus_scan_skipped?( scan_result: )
  18. 3 return false if scan_result.blank?
  19. 2 scan_result.start_with? 'scan skipped'
  20. end
  21. 1 def virus_scan_timestamp_now
  22. 1 Time.now.to_formatted_s(:db )
  23. end
  24. end
  25. end

app/services/deepblue/yaml_populate_service.rb

75.49% lines covered

408 relevant lines. 308 lines covered and 100 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 class YamlPopulateService
  4. 1 DEFAULT_CREATE_ZERO_LENGTH_FILES = true
  5. 1 DEFAULT_OVERWRITE_EXPORT_FILES = true
  6. 1 attr_accessor :mode, :source
  7. # TODO: count these
  8. 1 attr_reader :total_collections_exported, :total_file_sets_exported, :total_works_exported, :total_users_exported
  9. 1 attr_accessor :overwrite_export_files, :create_zero_length_files
  10. 1 def initialize( create_zero_length_files: DEFAULT_CREATE_ZERO_LENGTH_FILES,
  11. mode: MetadataHelper::MODE_BUILD,
  12. overwrite_export_files: DEFAULT_OVERWRITE_EXPORT_FILES,
  13. source: MetadataHelper::DEFAULT_SOURCE )
  14. 67 @create_zero_length_files = create_zero_length_files
  15. 67 @mode = mode
  16. 67 @overwrite_export_files = overwrite_export_files
  17. 67 @source = source
  18. 67 @total_collections_exported = 0
  19. 67 @total_file_sets_exported = 0
  20. 67 @total_file_sets_size_exported = 0
  21. 67 @total_works_exported = 0
  22. 67 @total_users_exported = 0
  23. end
  24. 1 def yaml_body_collections( out, indent:, curation_concern: )
  25. 1 @total_collections_exported += 1
  26. 1 yaml_item( out, indent, ":id:", curation_concern.id )
  27. 1 if source == MetadataHelper::SOURCE_DBDv2
  28. 1 yaml_item( out, indent, ":collection_type:", curation_concern.collection_type.machine_id, escape: true )
  29. end
  30. 1 yaml_item( out, indent, ":edit_users:", curation_concern.edit_users, escape: true )
  31. 1 yaml_item_prior_identifier( out, indent, curation_concern: curation_concern )
  32. 1 yaml_item_subject( out, indent, curation_concern: curation_concern )
  33. 1 yaml_item( out, indent, ":total_work_count:", curation_concern.work_ids.count )
  34. 1 yaml_item( out, indent, ":total_file_size:", curation_concern.total_file_size )
  35. 1 yaml_item( out,
  36. indent,
  37. ":total_file_size_human_readable:",
  38. human_readable_size( curation_concern.total_file_size ),
  39. escape: true )
  40. 1 yaml_item( out, indent, ":visibility:", curation_concern.visibility )
  41. 1 skip = %w[ prior_identifier rights rights_license subject subject_discipline total_file_size ]
  42. 1 attribute_names_collection.each do |name|
  43. 7 next if skip.include? name
  44. 1 yaml_item_collection( out, indent, curation_concern, name: name )
  45. end
  46. end
  47. 1 def yaml_file_size( file_set )
  48. 3 if file_set.file_size.blank?
  49. 2 file_set.original_file.nil? ? 0 : file_set.original_file.size
  50. else
  51. 1 file_set.file_size[0]
  52. end
  53. end
  54. 1 def yaml_body_files( out, indent_base:, indent:, curation_concern:, target_dirname: )
  55. 2 indent_first_line = indent
  56. 2 yaml_line( out, indent_first_line, ':file_set_ids:' )
  57. 2 return unless curation_concern.file_sets.count.positive?
  58. 1 indent = indent_base + indent_first_line + "-"
  59. 1 curation_concern.file_sets.each do |file_set|
  60. 1 yaml_item( out, indent, '', file_set.id, escape: true )
  61. end
  62. 1 curation_concern.file_sets.each do |file_set|
  63. 1 @total_file_sets_exported += 1
  64. 1 log_provenance_migrate( curation_concern: file_set, parent: curation_concern ) if MetadataHelper::MODE_MIGRATE == mode
  65. 1 file_id = ":#{yaml_file_set_id( file_set )}:"
  66. 1 yaml_line( out, indent_first_line, file_id )
  67. 1 indent = indent_base + indent_first_line
  68. 1 yaml_item( out, indent, ':id:', file_set.id, escape: true )
  69. 1 single_value = 1 == file_set.title.size
  70. 1 yaml_item( out, indent, ':title:', file_set.title, escape: true, single_value: single_value )
  71. 1 yaml_item_prior_identifier( out, indent, curation_concern: file_set )
  72. 1 file_path = yaml_export_file_path( target_dirname: target_dirname, file_set: file_set )
  73. 1 yaml_item( out, indent, ':file_path:', file_path.to_s, escape: true )
  74. 1 checksum = yaml_file_set_checksum( file_set: file_set )
  75. 1 yaml_item( out, indent, ":checksum_algorithm:", checksum.present? ? checksum.algorithm : '', escape: true )
  76. 1 yaml_item( out, indent, ":checksum_value:", checksum.present? ? checksum.value : '', escape: true )
  77. 1 yaml_item( out, indent, ":edit_users:", file_set.edit_users, escape: true )
  78. 1 file_size = yaml_file_size(file_set)
  79. # puts "\nfile_size=#{file_size} file_size.class=#{file_size.class.name}\n" unless file_size.is_a? Integer
  80. 1 @total_file_sets_size_exported += file_size.to_i
  81. 1 yaml_item( out, indent, ":file_size:", file_size )
  82. 1 yaml_item( out, indent, ":file_size_human_readable:", human_readable_size( file_size ), escape: true )
  83. 1 yaml_item( out, indent, ":mime_type:", file_set.mime_type, escape: true )
  84. 1 value = file_set.original_checksum.blank? ? '' : file_set.original_checksum[0]
  85. 1 yaml_item( out, indent, ":original_checksum:", value )
  86. 1 value = file_set.original_file.nil? ? nil : file_set.original_file.original_name
  87. 1 yaml_item( out, indent, ":original_name:", value, escape: true )
  88. 1 yaml_item( out, indent, ":visibility:", file_set.visibility )
  89. 1 skip = %w[ title file_size ]
  90. 1 attribute_names_file_set.each do |name|
  91. 3 next if skip.include? name
  92. 1 yaml_item_file_set( out, indent, file_set, name: name )
  93. end
  94. end
  95. end
  96. 1 def yaml_body_user_body( out, indent_base:, indent:, user: )
  97. 1 @total_users_exported += 1
  98. 1 indent_first_line = indent
  99. 1 user_email = ":#{yaml_user_email( user )}:"
  100. 1 yaml_line( out, indent_first_line, user_email )
  101. 1 indent = indent_base + indent_first_line
  102. 1 yaml_item(out, indent, ':email:', user.email, escape: true )
  103. 1 skip = %w[ email ]
  104. 1 attribute_names_user.each do |name|
  105. 2 next if skip.include? name
  106. 1 yaml_item_user(out, indent, user, name: name )
  107. end
  108. end
  109. 1 def yaml_body_users( out, indent_base:, indent:, users: )
  110. 2 yaml_item( out, indent, ":total_user_count:", users.count )
  111. 2 indent_first_line = indent
  112. 2 yaml_line( out, indent_first_line, ':user_emails:' )
  113. 2 return unless users.count.positive?
  114. 1 indent = indent_base + indent_first_line + "-"
  115. 1 users.each do |user|
  116. 3 yaml_item( out, indent, '', user.email, escape: true )
  117. end
  118. end
  119. 1 def yaml_body_works( out, indent:, curation_concern: )
  120. 2 @total_works_exported += 1
  121. 2 yaml_item( out, indent, ":id:", curation_concern.id )
  122. 2 yaml_item( out, indent, ":admin_set_id:", curation_concern.admin_set_id, escape: true )
  123. 2 yaml_item( out, indent, ":edit_users:", curation_concern.edit_users, escape: true )
  124. 2 yaml_item_prior_identifier( out, indent, curation_concern: curation_concern )
  125. 2 yaml_item_rights( out, indent, curation_concern: curation_concern )
  126. 2 yaml_item_subject( out, indent, curation_concern: curation_concern )
  127. 2 yaml_item( out, indent, ":total_file_count:", curation_concern.file_set_ids.count )
  128. 2 yaml_item( out, indent, ":total_file_size:", curation_concern.total_file_size )
  129. 2 yaml_item( out,
  130. indent,
  131. ":total_file_size_human_readable:",
  132. human_readable_size( curation_concern.total_file_size ),
  133. escape: true )
  134. 2 yaml_item( out, indent, ":visibility:", curation_concern.visibility )
  135. 2 skip = %w[ prior_identifier rights rights_license subject subject_discipline total_file_size ]
  136. 2 attribute_names_work.each do |name|
  137. 7 next if skip.include? name
  138. 1 yaml_item_work( out, indent, curation_concern, name: name )
  139. end
  140. end
  141. 1 def yaml_escape_value( value, comment: false, escape: false )
  142. 5 return "" if value.nil?
  143. 4 return value unless escape
  144. 3 return value if comment
  145. 2 value = value.to_json
  146. 2 return "" if "\"\"" == value
  147. 1 return value
  148. end
  149. 1 def yaml_export_file_path( target_dirname:, file_set: )
  150. 1 export_file_name = yaml_export_file_name( file_set: file_set )
  151. 1 target_dirname.join "#{file_set.id}_#{export_file_name}"
  152. end
  153. 1 def yaml_export_file_name( file_set: )
  154. 2 title = file_set.title[0]
  155. 2 file = MetadataHelper.file_from_file_set( file_set )
  156. 2 if file.nil?
  157. 1 rv = "nil_file"
  158. else
  159. 1 rv = file&.original_name
  160. 1 rv = "nil_original_file" if rv.nil?
  161. end
  162. 2 rv = title unless title == rv
  163. 2 rv = rv.gsub( /[\/\?\<\>\\\:\*\|\'\"\^\;]/, '_' )
  164. 2 return rv
  165. end
  166. 1 def yaml_file_set_checksum( file_set: )
  167. 2 file = MetadataHelper.file_from_file_set( file_set )
  168. 2 return file.checksum if file.present?
  169. return nil
  170. end
  171. 1 def yaml_file_set_id( file_set )
  172. "f_#{file_set.id}"
  173. end
  174. 1 def yaml_filename( pathname_dir:, id:, prefix:, task: )
  175. pathname_dir = Pathname.new pathname_dir unless pathname_dir.is_a? Pathname
  176. pathname_dir.join "#{prefix}#{id}_#{task}.yml"
  177. end
  178. 1 def yaml_filename_collection( pathname_dir:, collection:, task: MetadataHelper::DEFAULT_TASK )
  179. 1 yaml_filename( pathname_dir: pathname_dir, id: collection.id, prefix: MetadataHelper::PREFIX_COLLECTION, task: task )
  180. end
  181. 1 def yaml_filename_users( pathname_dir:, task: MetadataHelper::DEFAULT_TASK )
  182. 1 yaml_filename( pathname_dir: pathname_dir, id: '', prefix: MetadataHelper::PREFIX_USERS, task: task )
  183. end
  184. 1 def yaml_filename_work( pathname_dir:, work:, task: MetadataHelper::DEFAULT_TASK )
  185. 1 yaml_filename( pathname_dir: pathname_dir, id: work.id, prefix: MetadataHelper::PREFIX_WORK, task: task )
  186. end
  187. 1 def yaml_header( out, indent:, curation_concern:, header_type: )
  188. 1 yaml_line( out, indent, ':email:', curation_concern.depositor )
  189. 1 yaml_line( out, indent, ':visibility:', curation_concern.visibility )
  190. 1 yaml_line( out, indent, ':ingester:', '' )
  191. 1 yaml_line( out, indent, ':source:', source )
  192. 1 yaml_line( out, indent, ':export_timestamp:', DateTime.now.to_s )
  193. 1 yaml_line( out, indent, ':mode:', mode )
  194. 1 yaml_line( out, indent, ':id:', curation_concern.id )
  195. 1 yaml_line( out, indent, header_type )
  196. end
  197. 1 def yaml_header_populate( out, indent:, rake_task: 'umrdr:populate', target_filename: )
  198. 1 yaml_line( out, indent, target_filename.to_s, comment: true )
  199. 1 yaml_line( out, indent, "bundle exec rake #{rake_task}[#{target_filename}]", comment: true )
  200. 1 yaml_line( out, indent, "---" )
  201. 1 yaml_line( out, indent, ':user:' )
  202. end
  203. 1 def yaml_header_users( out, indent:, header_type: MetadataHelper::HEADER_TYPE_USERS )
  204. 1 yaml_line( out, indent, ':ingester:', '' )
  205. 1 yaml_line( out, indent, ':source:', source )
  206. 1 yaml_line( out, indent, ':export_timestamp:', DateTime.now.to_s )
  207. 1 yaml_line( out, indent, ':mode:', mode )
  208. 1 yaml_line( out, indent, header_type )
  209. end
  210. 1 def yaml_is_a_work?( curation_concern: )
  211. 4 if source == MetadataHelper::SOURCE_DBDv2
  212. 2 curation_concern.is_a? DataSet
  213. else
  214. 2 curation_concern.is_a? GenericWork
  215. end
  216. end
  217. 1 def yaml_item( out,
  218. indent,
  219. label,
  220. value = '',
  221. single_value: false,
  222. comment: false,
  223. indent_base: " ",
  224. label_postfix: ' ',
  225. escape: false )
  226. indent = "# #{indent}" if comment
  227. if single_value && value.present? && value.respond_to?( :each )
  228. value = value[0]
  229. out.puts "#{indent}#{label}#{label_postfix}#{yaml_escape_value( value, comment: comment, escape: escape )}"
  230. elsif value.respond_to?(:each)
  231. out.puts "#{indent}#{label}#{label_postfix}"
  232. indent += indent_base
  233. value.each { |item| out.puts "#{indent}- #{yaml_escape_value( item, comment: comment, escape: escape )}" }
  234. else
  235. out.puts "#{indent}#{label}#{label_postfix}#{yaml_escape_value( value, comment: comment, escape: escape )}"
  236. end
  237. end
  238. 1 def yaml_item_collection( out, indent, curation_concern, name: )
  239. 9 return if MetadataHelper::ATTRIBUTE_NAMES_IGNORE.include? name
  240. 2 label = ":#{name}:"
  241. 2 value = curation_concern[name]
  242. 2 return if value.blank? && !MetadataHelper::ATTRIBUTE_NAMES_ALWAYS_INCLUDE_CC.include?( name )
  243. 1 yaml_item( out, indent, label, value, escape: true )
  244. end
  245. 1 def yaml_item_file_set( out, indent, file_set, name: )
  246. 9 return if MetadataHelper::ATTRIBUTE_NAMES_IGNORE.include? name
  247. 2 label = ":#{name}:"
  248. 2 value = file_set[name]
  249. 2 return if value.blank? && !MetadataHelper::ATTRIBUTE_NAMES_ALWAYS_INCLUDE_FILE_SET.include?( name )
  250. 1 yaml_item( out, indent, label, value, escape: true )
  251. end
  252. 1 def yaml_item_prior_identifier( out, indent, curation_concern: )
  253. 2 if source == MetadataHelper::SOURCE_DBDv1
  254. 1 yaml_item( out, indent, ":prior_identifier:", '' )
  255. else
  256. # ids = curation_concern.prior_identifier
  257. # ids = [] if ids.nil?
  258. # ids << curation_concern.id
  259. # yaml_item( out, indent, ':prior_identifier:', ActiveSupport::JSON.encode( ids ) )
  260. 1 yaml_item( out, indent, ":prior_identifier:", curation_concern.prior_identifier )
  261. end
  262. end
  263. 1 def yaml_item_referenced_by( out, indent, curation_concern: )
  264. 2 if source == MetadataHelper::SOURCE_DBDv1
  265. 1 yaml_item( out, indent, ":isReferencedBy:", curation_concern.isReferencedBy, escape: true )
  266. else
  267. 1 yaml_item( out, indent, ":referenced_by:", curation_concern.referenced_by, escape: true )
  268. end
  269. end
  270. 1 def yaml_item_rights( out, indent, curation_concern: )
  271. 2 if source == MetadataHelper::SOURCE_DBDv1
  272. 1 yaml_item( out, indent, ":rights:", curation_concern.rights, escape: true )
  273. else
  274. 1 yaml_item( out, indent, ":rights_license:", curation_concern.rights_license, escape: true )
  275. end
  276. end
  277. 1 def yaml_item_subject( out, indent, curation_concern: )
  278. 2 if source == MetadataHelper::SOURCE_DBDv1
  279. 1 yaml_item( out, indent, ":subject:", curation_concern.subject, escape: true )
  280. else
  281. 1 yaml_item( out, indent, ":subject_discipline:", curation_concern.subject_discipline, escape: true )
  282. end
  283. end
  284. 1 def yaml_item_user( out, indent, user, name: )
  285. 6 return if MetadataHelper::ATTRIBUTE_NAMES_USER_IGNORE.include? name
  286. 2 label = ":#{name}:"
  287. 2 value = user[name]
  288. 2 return if value.blank? && !MetadataHelper::ATTRIBUTE_NAMES_ALWAYS_INCLUDE_USER.include?( name )
  289. 1 yaml_item( out, indent, label, value, escape: true )
  290. end
  291. 1 def yaml_item_work( out, indent, curation_concern, name: )
  292. 9 return if MetadataHelper::ATTRIBUTE_NAMES_IGNORE.include? name
  293. 2 label = ":#{name}:"
  294. 2 value = curation_concern[name]
  295. 2 return if value.blank? && !MetadataHelper::ATTRIBUTE_NAMES_ALWAYS_INCLUDE_CC.include?( name )
  296. 1 yaml_item( out, indent, label, value, escape: true )
  297. end
  298. 1 def yaml_line( out, indent, label, value = '', comment: false, label_postfix: ' ', escape: false )
  299. 2 indent = "# #{indent}" if comment
  300. 2 out.puts "#{indent}#{label}#{label_postfix}#{yaml_escape_value( value, comment: comment, escape: escape )}"
  301. end
  302. 1 def yaml_populate_collection( collection:,
  303. dir: MetadataHelper::DEFAULT_BASE_DIR,
  304. out: nil,
  305. populate_works: true,
  306. export_files: true,
  307. target_filename: nil,
  308. target_dirname: nil )
  309. 3 target_file = nil
  310. 3 dir = Pathname.new dir unless dir.is_a? Pathname
  311. 3 if out.nil?
  312. collection = Collection.find collection if collection.is_a? String
  313. target_file = yaml_filename_collection( pathname_dir: dir, collection: collection )
  314. target_dir = yaml_targetdir_collection( pathname_dir: dir, collection: collection )
  315. Dir.mkdir( target_dir ) if export_files && !Dir.exist?( target_dir )
  316. open( target_file, 'w' ) do |out2|
  317. yaml_populate_collection( collection: collection,
  318. out: out2,
  319. populate_works: populate_works,
  320. export_files: false,
  321. target_filename: target_file,
  322. target_dirname: target_dir )
  323. end
  324. if export_files
  325. collection.member_objects.each do |work|
  326. next unless yaml_is_a_work?( curation_concern: work )
  327. yaml_work_export_files( work: work, target_dirname: target_dir )
  328. end
  329. end
  330. else
  331. 3 log_provenance_migrate( curation_concern: collection ) if MetadataHelper::MODE_MIGRATE == mode
  332. 3 indent_base = " " * 2
  333. 3 indent = indent_base * 0
  334. 3 yaml_header_populate( out, indent: indent, target_filename: target_filename )
  335. 3 indent = indent_base * 1
  336. 3 yaml_header( out,
  337. indent: indent,
  338. curation_concern: collection,
  339. header_type: MetadataHelper::HEADER_TYPE_COLLECTIONS )
  340. 3 indent = indent_base * 2
  341. 3 yaml_body_collections( out, indent: indent, curation_concern: collection )
  342. 3 return unless populate_works
  343. 2 return unless collection.member_objects.size.positive?
  344. 1 indent = indent_base * 2
  345. 1 yaml_line( out, indent, MetadataHelper::HEADER_TYPE_WORKS )
  346. 1 indent = indent_base + indent + "-"
  347. 1 collection.member_objects.each do |work|
  348. 2 next unless yaml_is_a_work?( curation_concern: work )
  349. 1 yaml_item( out, indent, '', work.id, escape: true )
  350. end
  351. 1 indent = indent_base * 2
  352. 1 collection.member_objects.each do |work|
  353. 2 next unless yaml_is_a_work?( curation_concern: work )
  354. 1 indent = indent_base * 2
  355. 1 yaml_line( out, indent, ":works_#{work.id}:" )
  356. 1 indent = indent_base * 3
  357. 1 log_provenance_migrate( curation_concern: work, parent: collection ) if MetadataHelper::MODE_MIGRATE == mode
  358. 1 yaml_body_works( out, indent: indent, curation_concern: work )
  359. 1 yaml_body_files( out,
  360. indent_base: indent_base,
  361. indent: indent,
  362. curation_concern: work,
  363. target_dirname: target_dirname )
  364. end
  365. end
  366. end
  367. 1 def yaml_populate_stats
  368. 1 stats = {}
  369. 1 stats[:total_collections_exported] = @total_collections_exported
  370. 1 stats[:total_works_exported] = @total_works_exported
  371. 1 stats[:total_file_sets_exported] = @total_file_sets_exported
  372. 1 stats[:total_file_sets_size_exported] = @total_file_sets_size_exported
  373. 1 stats[:total_file_sets_size_readable_exported] = human_readable_size @total_file_sets_size_exported
  374. 1 stats[:total_users_exported] = @total_users_exported
  375. 1 return stats
  376. end
  377. 1 def yaml_populate_users( dir: MetadataHelper::DEFAULT_BASE_DIR, out: nil, target_filename: nil )
  378. 1 target_file = nil
  379. 1 dir = Pathname.new dir unless dir.is_a? Pathname
  380. 1 Dir.mkdir( dir ) unless Dir.exist? dir
  381. 1 if out.nil?
  382. target_file = yaml_filename_users( pathname_dir: dir, task: mode )
  383. open( target_file, 'w' ) do |out2|
  384. yaml_populate_users( out: out2, target_filename: target_file )
  385. end
  386. else
  387. # log_provenance_migrate( curation_concern: curation_concern ) if MetadataHelper::MODE_MIGRATE == mode
  388. 1 indent_base = " " * 2
  389. 1 indent = indent_base * 0
  390. 1 yaml_header_populate( out, indent: indent, rake_task: 'umrdr:populate_users', target_filename: target_filename )
  391. 1 indent = indent_base * 1
  392. 1 yaml_header_users( out, indent: indent )
  393. 1 indent = indent_base * 2
  394. 1 users = User.all
  395. 1 yaml_body_users( out, indent_base: indent_base, indent: indent, users: users )
  396. 1 users.each do |user|
  397. 1 yaml_body_user_body( out, indent_base: indent_base, indent: indent, user: user )
  398. end
  399. end
  400. 1 return target_file
  401. end
  402. 1 def yaml_populate_work( curation_concern:,
  403. dir: MetadataHelper::DEFAULT_BASE_DIR,
  404. out: nil,
  405. export_files: true,
  406. target_filename: nil,
  407. target_dirname: nil )
  408. 2 target_file = nil
  409. 2 dir = Pathname.new dir unless dir.is_a? Pathname
  410. 2 if out.nil?
  411. curation_concern = yaml_work_find( curation_concern: curation_concern ) if curation_concern.is_a? String
  412. target_file = yaml_filename_work( pathname_dir: dir, work: curation_concern )
  413. target_dir = yaml_targetdir_work( pathname_dir: dir, work: curation_concern )
  414. Dir.mkdir( target_dir ) if export_files && !Dir.exist?( target_dir )
  415. open( target_file, 'w' ) do |out2|
  416. yaml_populate_work( curation_concern: curation_concern,
  417. out: out2,
  418. export_files: export_files,
  419. target_filename: target_file,
  420. target_dirname: target_dir )
  421. end
  422. if export_files
  423. yaml_work_export_files( work: curation_concern, target_dirname: target_dir )
  424. end
  425. else
  426. 2 log_provenance_migrate( curation_concern: curation_concern ) if MetadataHelper::MODE_MIGRATE == mode
  427. 2 indent_base = " " * 2
  428. 2 indent = indent_base * 0
  429. 2 yaml_header_populate( out, indent: indent, target_filename: target_filename )
  430. 2 indent = indent_base * 1
  431. 2 yaml_header( out,
  432. indent: indent,
  433. curation_concern: curation_concern,
  434. header_type: MetadataHelper::HEADER_TYPE_WORKS )
  435. 2 indent = indent_base * 2
  436. 2 yaml_body_works( out, indent: indent, curation_concern: curation_concern )
  437. 2 yaml_body_files( out,
  438. indent_base: indent_base,
  439. indent: indent,
  440. curation_concern: curation_concern,
  441. target_dirname: target_dirname )
  442. end
  443. 2 return target_file
  444. end
  445. 1 def yaml_targetdir( pathname_dir:, id:, prefix:, task: )
  446. pathname_dir = Pathname.new pathname_dir unless pathname_dir.is_a? Pathname
  447. pathname_dir.join "#{prefix}#{id}_#{task}"
  448. end
  449. 1 def yaml_targetdir_collection( pathname_dir:, collection:, task: MetadataHelper::DEFAULT_TASK )
  450. 1 yaml_targetdir( pathname_dir: pathname_dir, id: collection.id, prefix: MetadataHelper::PREFIX_COLLECTION, task: task )
  451. end
  452. 1 def yaml_targetdir_users( pathname_dir:, task: MetadataHelper::DEFAULT_TASK )
  453. 1 yaml_targetdir( pathname_dir: pathname_dir, id: '', prefix: MetadataHelper::PREFIX_USERS, task: task )
  454. end
  455. 1 def yaml_targetdir_work( pathname_dir:, work:, task: MetadataHelper::DEFAULT_TASK )
  456. 1 yaml_targetdir( pathname_dir: pathname_dir, id: work.id, prefix: MetadataHelper::PREFIX_WORK, task: task )
  457. end
  458. 1 def yaml_user_email( user )
  459. 1 "user_#{user.email}"
  460. end
  461. 1 def yaml_work_export_files( work:, target_dirname: nil, log_filename: nil )
  462. 1 log_file = target_dirname.join ".export.log" if log_filename.nil?
  463. 1 open( log_file, 'w' ) { |f| f.write('') } # erase log file
  464. start_time = Time.now
  465. log_lines( log_file,
  466. "Starting yaml work export of files at #{start_time} ...",
  467. "Generic work id: #{work.id}",
  468. "Total file count: #{work.file_sets.count}")
  469. total_byte_count = 0
  470. if work.file_sets.count.positive?
  471. work.file_sets.each do |file_set|
  472. export_file_name = yaml_export_file_path( target_dirname: target_dirname, file_set: file_set )
  473. write_file = if overwrite_export_files
  474. true
  475. else
  476. !File.exist?( export_file_name )
  477. end
  478. file = MetadataHelper.file_from_file_set( file_set )
  479. file_size = if file_set.file_size.blank?
  480. file_set.original_file.nil? ? 0 : file_set.original_file.size
  481. else
  482. file_set.file_size[0]
  483. end
  484. export_what = "#{export_file_name} (#{human_readable_size(file_size)} / #{file_size} bytes)"
  485. if write_file && file.present?
  486. source_uri = file.uri.value
  487. log_lines( log_file, "Starting file export of #{export_what} at #{Time.now}." )
  488. bytes_copied = ExportFilesHelper.export_file_uri( source_uri: source_uri, target_file: export_file_name )
  489. total_byte_count += bytes_copied
  490. log_lines( log_file, "Finished file export of #{export_what} at #{Time.now}." )
  491. elsif write_file && file.nil? && export_file_name.present?
  492. if create_zero_length_files
  493. log_lines( log_file, "File export of file_set #{file_set.id} -- #{export_what} at #{Time.now} creating zero length file because file is nil." )
  494. open( export_file_name, 'w' ) { |out| out.write( '' ) }
  495. else
  496. log_lines( log_file, "WARNING: Skipping file export of file_set #{file_set.id} -- #{export_what} at #{Time.now} because file is nil." )
  497. end
  498. elsif write_file && file.nil?
  499. log_lines( log_file, "WARNING: Skipping file export of file_set #{file_set.id} -- #{export_what} at #{Time.now} because file is nil and export_file_name is empty." )
  500. else
  501. log_lines( log_file, "Skipping file export of #{export_what} at #{Time.now}." )
  502. end
  503. end
  504. end
  505. end_time = Time.now
  506. log_lines( log_file,
  507. "Total bytes exported: #{total_byte_count} (#{human_readable_size(total_byte_count)})",
  508. "... finished yaml generic work export of files at #{end_time}.")
  509. rescue Exception => e # rubocop:disable Lint/RescueException
  510. # rubocop:disable Rails/Output
  511. 1 puts "#{e.class}: #{e.message} at #{e.backtrace.join("\n")}"
  512. # rubocop:enable Rails/Output
  513. end
  514. 1 def yaml_work_find( curation_concern: )
  515. 2 if source == MetadataHelper::SOURCE_DBDv2
  516. 1 DataSet.find curation_concern
  517. else
  518. 1 GenericWork.find curation_concern
  519. end
  520. end
  521. 1 def self.init_attribute_names_always_include_cc
  522. rv = {}
  523. MetadataHelper::ATTRIBUTE_NAMES_ALWAYS_INCLUDE_CC.each { |name| rv[name] = true }
  524. return rv
  525. end
  526. 1 protected
  527. 1 def attribute_names_always_include_cc
  528. @@attribute_names_always_include ||= init_attribute_names_always_include_cc
  529. end
  530. 1 def attribute_names_collection
  531. @@attribute_names_collection ||= Collection.attribute_names.sort
  532. end
  533. 1 def attribute_names_file_set
  534. @@attribute_names_file_set ||= FileSet.attribute_names.sort
  535. end
  536. 1 def attribute_names_user
  537. @@attribute_names_user ||= User.attribute_names.sort
  538. end
  539. 1 def attribute_names_work
  540. if source == MetadataHelper::SOURCE_DBDv2
  541. DataSet.attribute_names.sort
  542. else
  543. GenericWork.attribute_names.sort
  544. end
  545. end
  546. 1 def file_from_file_set( file_set )
  547. file = nil
  548. files = file_set.files
  549. unless files.nil? || files.size.zero?
  550. file = files[0]
  551. files.each do |f|
  552. file = f unless f.original_name.empty?
  553. end
  554. end
  555. return file
  556. end
  557. 1 def human_readable_size( value )
  558. value = value.to_i
  559. return ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert( value, precision: 3 )
  560. end
  561. 1 def log_lines( filename, *lines )
  562. File.open( filename, "a" ) do |f|
  563. lines.each { |line| f.puts line }
  564. end
  565. end
  566. 1 def log_provenance_migrate( curation_concern:, parent: nil, migrate_direction: 'export' )
  567. if source == MetadataHelper::SOURCE_DBDv1
  568. msg = "Migrate #{migrate_direction} #{curation_concern.class.name} #{curation_concern.id}"
  569. msg += " parent_id: #{parent.id}" if parent.present?
  570. PROV_LOGGER.info( msg )
  571. else
  572. return unless curation_concern.respond_to? :provenance_migrate
  573. parent_id = nil
  574. parent_id = parent.id if parent.present?
  575. curation_concern.provenance_migrate( current_user: nil,
  576. parent_id: parent_id,
  577. migrate_direction: migrate_direction )
  578. end
  579. end
  580. 1 def metadata_filename_collection( pathname_dir, collection )
  581. pathname_dir.join "w_#{collection.id}_metadata_report.txt"
  582. end
  583. 1 def metadata_filename_collection_work( pathname_dir, collection, work )
  584. pathname_dir.join "c_#{collection.id}_w_#{work.id}_metadata_report.txt"
  585. end
  586. 1 def metadata_filename_work( pathname_dir, work )
  587. pathname_dir.join "w_#{work.id}_metadata_report.txt"
  588. end
  589. 1 def metadata_multi_valued?( attribute_value )
  590. return false if attribute_value.blank?
  591. return true if attribute_value.respond_to?( :each ) && 1 < attribute_value.size
  592. false
  593. end
  594. end
  595. end

app/services/hyrax/collections/collection_member_service.rb

51.61% lines covered

31 relevant lines. 16 lines covered and 15 lines missed.
    
  1. 1 module Hyrax
  2. 1 module Collections
  3. # Responsible for retrieving collection members
  4. 1 class CollectionMemberService
  5. 1 attr_reader :scope, :params, :collection
  6. 1 delegate :repository, to: :scope
  7. # @param scope [#repository] Typically a controller object which responds to :repository
  8. # @param [Collection]
  9. # @param [ActionController::Parameters] query params
  10. 1 def initialize(scope:, collection:, params:)
  11. @scope = scope
  12. @collection = collection
  13. @params = params
  14. end
  15. # @api public
  16. #
  17. # Collections which are members of the given collection
  18. # @return [Blacklight::Solr::Response] {up to 50 solr documents}
  19. 1 def available_member_subcollections
  20. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  21. ::Deepblue::LoggingHelper.called_from,
  22. "subcollections_search_builder=#{subcollections_search_builder}",
  23. "params_for_subcollections=#{params_for_subcollections}",
  24. "" ]
  25. query_solr(query_builder: subcollections_search_builder, query_params: params_for_subcollections)
  26. end
  27. # @api public
  28. #
  29. # Works which are members of the given collection
  30. # @return [Blacklight::Solr::Response]
  31. 1 def available_member_works
  32. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  33. ::Deepblue::LoggingHelper.called_from,
  34. "works_search_builder=#{works_search_builder}",
  35. "params=#{params}",
  36. "" ]
  37. query_solr(query_builder: works_search_builder, query_params: params)
  38. end
  39. # @api public
  40. #
  41. # Work ids of the works which are members of the given collection
  42. # @return [Blacklight::Solr::Response]
  43. 1 def available_member_work_ids
  44. query_solr_with_field_selection(query_builder: work_ids_search_builder, fl: 'id')
  45. end
  46. 1 private
  47. # @api private
  48. #
  49. # set up a member search builder for works only
  50. # @return [CollectionMemberSearchBuilder] new or existing
  51. 1 def works_search_builder
  52. @works_search_builder ||= Hyrax::CollectionMemberSearchBuilder.new(scope: scope, collection: collection, search_includes_models: :works)
  53. end
  54. # @api private
  55. #
  56. # set up a member search builder for collections only
  57. # @return [CollectionMemberSearchBuilder] new or existing
  58. 1 def subcollections_search_builder
  59. @subcollections_search_builder ||= Hyrax::CollectionMemberSearchBuilder.new(scope: scope, collection: collection, search_includes_models: :collections)
  60. end
  61. # @api private
  62. #
  63. # set up a member search builder for returning work ids only
  64. # @return [CollectionMemberSearchBuilder] new or existing
  65. 1 def work_ids_search_builder
  66. @work_ids_search_builder ||= Hyrax::CollectionMemberSearchBuilder.new(scope: scope, collection: collection, search_includes_models: :works)
  67. end
  68. # @api private
  69. #
  70. 1 def query_solr(query_builder:, query_params:)
  71. repository.search(query_builder.with(query_params).query)
  72. end
  73. # @api private
  74. #
  75. 1 def query_solr_with_field_selection(query_builder:, fl:)
  76. repository.search(query_builder.merge(fl: fl).query)
  77. end
  78. # @api private
  79. #
  80. # Blacklight pagination still needs to be overridden and set up for the subcollections.
  81. # @return <Hash> the additional inputs required for the subcollection member search builder
  82. 1 def params_for_subcollections
  83. # To differentiate current page for works vs subcollections, we have to use a sub_collection_page
  84. # param. Map this to the page param before querying for subcollections, if it's present
  85. params[:page] = params.delete(:sub_collection_page)
  86. params
  87. end
  88. end
  89. end
  90. end

app/services/hyrax/embargo_service.rb

33.33% lines covered

33 relevant lines. 11 lines covered and 22 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hyrax
  3. 1 class EmbargoService < RestrictionService
  4. 1 class << self
  5. #
  6. # Methods for Querying Repository to find Embargoed Objects
  7. #
  8. # Returns all assets with embargo release date set to a date in the past
  9. 1 def assets_with_expired_embargoes
  10. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  11. ::Deepblue::LoggingHelper.called_from,
  12. "" ]
  13. builder = Hyrax::ExpiredEmbargoSearchBuilder.new(self)
  14. presenters(builder)
  15. end
  16. # Returns all assets with embargo release date set
  17. # (assumes that when lease visibility is applied to assets
  18. # whose leases have expired, the lease expiration date will be removed from its metadata)
  19. 1 def assets_under_embargo
  20. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  21. ::Deepblue::LoggingHelper.called_from,
  22. "" ]
  23. builder = Hyrax::EmbargoSearchBuilder.new(self)
  24. presenters(builder)
  25. end
  26. # Returns all assets that have had embargoes deactivated in the past.
  27. 1 def assets_with_deactivated_embargoes
  28. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  29. ::Deepblue::LoggingHelper.called_from,
  30. "" ]
  31. builder = Hyrax::DeactivatedEmbargoSearchBuilder.new(self)
  32. presenters(builder)
  33. end
  34. # Returns all assets with embargo release date set to a date in the past
  35. 1 def my_assets_with_expired_embargoes( current_user_key )
  36. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  37. ::Deepblue::LoggingHelper.called_from,
  38. "" ]
  39. builder = Hyrax::My::ExpiredEmbargoSearchBuilder.new(self)
  40. builder.current_user_key = current_user_key
  41. presenters(builder)
  42. end
  43. # Returns all assets with embargo release date set
  44. # (assumes that when lease visibility is applied to assets
  45. # whose leases have expired, the lease expiration date will be removed from its metadata)
  46. 1 def my_assets_under_embargo( current_user_key )
  47. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  48. ::Deepblue::LoggingHelper.called_from,
  49. "" ]
  50. builder = Hyrax::My::EmbargoSearchBuilder.new(self)
  51. builder.current_user_key = current_user_key
  52. presenters(builder)
  53. end
  54. # Returns all assets that have had embargoes deactivated in the past.
  55. 1 def my_assets_with_deactivated_embargoes( current_user_key )
  56. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  57. ::Deepblue::LoggingHelper.called_from,
  58. "" ]
  59. builder = Hyrax::My::DeactivatedEmbargoSearchBuilder.new(self)
  60. builder.current_user_key = current_user_key
  61. presenters(builder)
  62. end
  63. 1 private
  64. 1 def presenter_class
  65. Hyrax::EmbargoPresenter
  66. end
  67. end
  68. end
  69. end

app/validators/hydra/future_date_validator.rb

25.0% lines covered

12 relevant lines. 3 lines covered and 9 lines missed.
    
  1. # this monkey overrides Hydra::FutureDateValidator in the gem hydra-access-controls
  2. 1 module Hydra
  3. 1 class FutureDateValidator < ActiveModel::EachValidator
  4. 1 def validate_each(record, attribute, value)
  5. if value.present?
  6. begin
  7. if date = value.to_date
  8. if attribute.to_s == "embargo_release_date"
  9. return unless DeepBlueDocs::Application.config.embargo_enforce_future_release_date
  10. end
  11. if date <= Date.today
  12. # Deepblue::LoggingHelper.bold_debug [ Deepblue::LoggingHelper.here,
  13. # Deepblue::LoggingHelper.called_from,
  14. # "date=#{date}",
  15. # "attribute=#{attribute}" ] # + caller_locations(1, 40)
  16. record.errors[attribute] << "FutureDateValidator says Must be a future date"
  17. end
  18. else
  19. record.errors[attribute] << "Invalid Date Format"
  20. end
  21. rescue ArgumentError, NoMethodError
  22. record.errors[attribute] << "Invalid Date Format"
  23. end
  24. end
  25. end
  26. end
  27. end

config/application.rb

98.29% lines covered

117 relevant lines. 115 lines covered and 2 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require_relative 'boot'
  3. 1 require 'rails/all'
  4. # require 'app/model/concerns/hydra/access_controls/access_right'
  5. 1 require File.join(Gem::Specification.find_by_name("hydra-access-controls").full_gem_path, "app/models/concerns/hydra/access_controls/access_right.rb")
  6. # require_relative '../lib/rack_multipart_buf_size_setter.rb'
  7. # Require the gems listed in Gemfile, including any gems
  8. # you've limited to :test, :development, or :production.
  9. 1 Bundler.require(*Rails.groups)
  10. # rubocop:disable Rails/Output
  11. 1 module DeepBlueDocs
  12. 1 class Application < Rails::Application
  13. 1 config.autoload_paths += [Rails.root.join('lib')]
  14. 1 config.eager_load_paths += [Rails.root.join('lib')]
  15. # https://bibwild.wordpress.com/2016/12/27/a-class_eval-monkey-patching-pattern-with-prepend/
  16. 1 config.to_prepare do
  17. # Load any monkey-patching extensions in to_prepare for Rails dev-mode class-reloading.
  18. 1 Dir.glob(File.join(File.dirname(__FILE__), "../lib/extensions/extensions.rb")) do |c|
  19. 1 Rails.configuration.cache_classes ? require(c) : load(c)
  20. end
  21. end
  22. # Settings in config/environments/* take precedence over those specified here.
  23. # Application configuration should go into files in config/initializers
  24. # -- all .rb files in that directory are automatically loaded.
  25. #
  26. # reference config values like: DeepBlueDocs::Application.config.variable_name
  27. # Chimera configuration goes here
  28. # config.authentication_method = "generic"
  29. 1 config.authentication_method = "iu"
  30. # config.authentication_method = "umich"
  31. 1 config.generators do |g|
  32. 1 g.test_framework :rspec, spec: true
  33. end
  34. # config.middleware.insert_before Rack::Runtime, RackMultipartBufSizeSetter
  35. # config.dbd_version = 'DBDv1'
  36. 1 config.dbd_version = 'DBDv2'
  37. 1 config.show_masthead_announcement = false
  38. # puts "config.time_zone=#{config.time_zone}"
  39. 1 config.timezone_offset = DateTime.now.offset
  40. 1 config.timezone_zone = DateTime.now.zone
  41. 1 config.datetime_stamp_display_local_time_zone = true
  42. ## ensure tmp directories are defined
  43. 1 verbose_init = false
  44. 1 puts "ENV['TMPDIR']=#{ENV['TMPDIR']}" if verbose_init
  45. 1 puts "ENV['_JAVA_OPTIONS']=#{ENV['_JAVA_OPTIONS']}" if verbose_init
  46. 1 puts "ENV['JAVA_OPTIONS']=#{ENV['JAVA_OPTIONS']}" if verbose_init
  47. 1 tmpdir = ENV['TMPDIR']
  48. 1 if tmpdir.blank? || tmpdir == '/tmp' || tmpdir.start_with?( '/tmp/' )
  49. 1 tmpdir = File.absolute_path( './tmp/derivatives/' )
  50. 1 ENV['TMPDIR'] = tmpdir
  51. end
  52. 1 ENV['_JAVA_OPTIONS'] = "-Djava.io.tmpdir=#{tmpdir}" if ENV['_JAVA_OPTIONS'].blank?
  53. 1 ENV['JAVA_OPTIONS'] = "-Djava.io.tmpdir=#{tmpdir}" if ENV['JAVA_OPTIONS'].blank?
  54. 1 puts "ENV['TMPDIR']=#{ENV['TMPDIR']}"
  55. 1 puts "ENV['_JAVA_OPTIONS']=#{ENV['_JAVA_OPTIONS']}" if verbose_init
  56. 1 puts "ENV['JAVA_OPTIONS']=#{ENV['JAVA_OPTIONS']}" if verbose_init
  57. 1 puts `echo $TMPDIR`.to_s if verbose_init
  58. 1 puts `echo $_JAVA_OPTIONS`.to_s if verbose_init
  59. 1 puts `echo $JAVA_OPTIONS`.to_s if verbose_init
  60. # For properly generating URLs and minting DOIs - the app may not by default
  61. # Outside of a request context the hostname needs to be provided.
  62. 1 config.hostname = Settings.hostname
  63. # puts "config.hostname=#{config.hostname}"
  64. ## configure box
  65. 1 config.box_enabled = false
  66. 1 config.box_developer_token = nil # replace this with a developer token to override Single Auth
  67. # config.box_developer_token = 'IGmQMmqw8coKpuQDN3EG4gBrDzn78sGr'.freeze
  68. 1 config.box_dlib_dbd_box_user_id = '3200925346'
  69. 1 config.box_ulib_dbd_box_id = '45101723215'
  70. 1 config.box_verbose = true
  71. 1 config.box_always_report_not_logged_in_errors = true
  72. 1 config.box_create_dirs_for_empty_works = true
  73. 1 config.box_access_and_refresh_token_file = Rails.root.join( 'config', 'box_config.yml' ).freeze
  74. 1 config.box_access_and_refresh_token_file_init = Rails.root.join( 'config', 'box_config_init.yml' ).freeze
  75. 1 config.box_integration_enabled = config.box_enabled && ( !config.box_developer_token.nil? ||
  76. File.exist?( config.box_access_and_refresh_token_file ) )
  77. ## configure embargo
  78. 1 config.embargo_enforce_future_release_date = true # now that we have automated embargo expiration
  79. 1 config.embargo_visibility_after_default_status = ::Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
  80. 1 config.embargo_visibility_during_default_status = ::Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
  81. 1 config.embargo_manage_hide_files = true
  82. 1 config.embargo_allow_children_unembargo_choice = false
  83. 1 config.embargo_email_rds_hostnames = [ 'testing.deepblue.lib.umich.edu',
  84. 'staging.deepblue.lib.umich.edu',
  85. 'deepblue.lib.umich.edu' ].freeze
  86. 1 config.embargo_about_to_expire_email_rds = config.embargo_email_rds_hostnames.include? config.hostname
  87. 1 config.embargo_deactivate_email_rds = config.embargo_email_rds_hostnames.include? config.hostname
  88. ## configure for Globus
  89. # -- To enable Globus for development, create /deepbluedata-globus/download and /deepbluedata-globus/prep
  90. 1 config.globus_era_timestamp = Time.now.freeze
  91. 1 config.globus_era_token = config.globus_era_timestamp.to_s.freeze
  92. 1 if Rails.env.test?
  93. 1 config.globus_dir = '/tmp/deepbluedata-globus'
  94. 1 Dir.mkdir config.globus_dir unless Dir.exist? config.globus_dir
  95. else
  96. config.globus_dir = Settings.globus_dir
  97. end
  98. # puts "globus_dir=#{config.globus_dir}"
  99. 1 config.globus_dir = Pathname.new config.globus_dir
  100. 1 config.globus_download_dir = config.globus_dir.join 'download'
  101. 1 config.globus_prep_dir = config.globus_dir.join 'prep'
  102. 1 if Rails.env.test?
  103. 1 Dir.mkdir config.globus_download_dir unless Dir.exist? config.globus_download_dir
  104. 1 Dir.mkdir config.globus_prep_dir unless Dir.exist? config.globus_prep_dir
  105. end
  106. 1 config.globus_enabled = true && Dir.exist?( config.globus_download_dir ) && Dir.exist?( config.globus_prep_dir )
  107. 1 config.base_file_name = "DataCORE_"
  108. 1 config.globus_base_url = 'https://app.globus.org/file-manager?origin_id=99d8c648-a9ff-11e7-aedd-22000a92523b&origin_path=%2Fdownload%2F'
  109. 1 config.globus_restart_all_copy_jobs_quiet = true
  110. 1 config.globus_debug_delay_per_file_copy_job_seconds = 0
  111. 1 config.globus_after_copy_job_ui_delay_seconds = 3
  112. 1 if Rails.env.production?
  113. config.globus_copy_file_group = "dbdglobus"
  114. else
  115. 1 config.globus_copy_file_group = nil
  116. end
  117. 1 config.globus_copy_file_permissions = "u=rw,g=rw,o=r"
  118. # deposit notification email addresses
  119. 1 config.notification_email = Settings.notification_email
  120. 1 config.user_email = Settings.user_email
  121. 1 config.max_file_size = 2 * ( 1024 ** 3 )
  122. 1 config.max_file_size_str = ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert(config.max_file_size, {})
  123. 1 config.max_total_file_size = config.max_file_size * 5
  124. 1 config.max_total_file_size_str = ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert(config.max_total_file_size, {})
  125. 1 config.max_work_file_size_to_download = 10_000_000_000
  126. 1 config.min_work_file_size_to_download_warn = 1_000_000_000
  127. ## configure jira integration
  128. 1 config.jira_integration_hostnames = [ 'deepblue.local',
  129. 'testing.deepblue.lib.umich.edu',
  130. 'staging.deepblue.lib.umich.edu',
  131. 'deepblue.lib.umich.edu' ].freeze
  132. 1 config.jira_integration_hostnames_prod = [ 'deepblue.lib.umich.edu' ].freeze
  133. 1 config.jira_integration_enabled = config.jira_integration_hostnames.include? config.hostname
  134. 1 config.jira_test_mode = !config.jira_integration_hostnames_prod.include?( config.hostname )
  135. 1 config.jira_manager_project_key = 'DBHELP'
  136. 1 config.jira_manager_issue_type = 'Data Deposit'
  137. # config.jira_manager_project_key = 'BLUEDOC'
  138. # config.jira_manager_issue_type = 'Story'
  139. ### file upload and ingest
  140. 1 config.notify_user_file_upload_and_ingest_are_complete = true
  141. 1 config.notify_managers_file_upload_and_ingest_are_complete = true
  142. # ingest characterization config
  143. 1 config.characterize_excluded_ext_set = { '.csv' => 'text/plain' }.freeze # , '.nc' => 'text/plain' }.freeze
  144. 1 config.characterize_enforced_mime_type = { '.csv' => 'text/csv' }.freeze # , '.nc' => 'text/plain' }.freeze
  145. # ingest derivative config
  146. 1 config.derivative_excluded_ext_set = {}.freeze
  147. 1 config.derivative_max_file_size = 4_000_000_000 # set to -1 for no limit
  148. 1 config.derivative_max_file_size_str = ActiveSupport::NumberHelper::NumberToHumanSizeConverter.convert(config.derivative_max_file_size, precision: 3 )
  149. # URL for logging the user out of Cosign
  150. 1 config.logout_prefix = "https://weblogin.umich.edu/cgi-bin/logout?"
  151. # See references to: DeepBlueDocs::Application.config.relative_url_root
  152. 1 config.relative_url_root = Settings.relative_url_root unless Rails.env.test?
  153. # Set the default host for resolving _url methods
  154. 1 Rails.application.routes.default_url_options[:host] = config.hostname
  155. # ingest virus scan config
  156. 1 config.virus_scan_max_file_size = 4_000_000_000
  157. 1 config.virus_scan_retry = true
  158. 1 config.virus_scan_retry_on_error = false
  159. 1 config.virus_scan_retry_on_service_unavailable = true
  160. 1 config.virus_scan_retry_on_unknown = false
  161. 1 config.do_ordered_list_hack = true
  162. 1 config.do_ordered_list_hack_save = true
  163. 1 config.email_enabled = true
  164. 1 config.email_log_echo_to_rails_logger = true
  165. 1 config.provenance_log_name = "provenance_#{Rails.env}.log"
  166. 1 config.provenance_log_path = Rails.root.join( 'log', config.provenance_log_name )
  167. 1 config.provenance_log_echo_to_rails_logger = true
  168. 1 config.provenance_log_redundant_events = true
  169. 1 config.scheduler_log_echo_to_rails_logger = true
  170. 1 config.scheduler_job_file = 'scheduler_jobs_prod.yml'
  171. 1 config.scheduler_heartbeat_email_targets = [ 'fritx@umich.edu' ] # leave empty to disable
  172. 1 config.upload_log_echo_to_rails_logger = true
  173. end
  174. end
  175. # rubocop:enable Rails/Output

config/boot.rb

100.0% lines covered

2 relevant lines. 2 lines covered and 0 lines missed.
    
  1. 1 ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
  2. 1 require 'bundler/setup' # Set up gems listed in the Gemfile.

config/environment.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # Load the Rails application.
  2. 1 require_relative 'application'
  3. # load commit version for footer
  4. 1 ENV['SOURCE_COMMIT'] = `git rev-parse --short HEAD`.squish unless ENV['SOURCE_COMMIT'].present?
  5. 1 ENV['SOURCE_VERSION'] = `git describe --tags --abbrev=0`.squish unless ENV['SOURCE_VERSION'].present?
  6. # Initialize the Rails application.
  7. 1 Rails.application.initialize!

config/environments/test.rb

100.0% lines covered

15 relevant lines. 15 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require "email_logger"
  3. 1 require "provenance_logger"
  4. 1 Rails.application.configure do
  5. # Settings specified here will take precedence over those in config/application.rb.
  6. # The test environment is used exclusively to run your application's
  7. # test suite. You never need to work with it otherwise. Remember that
  8. # your test database is "scratch space" for the test suite and is wiped
  9. # and recreated between test runs. Don't rely on the data there!
  10. 1 config.cache_classes = true
  11. # Do not eager load code on boot. This avoids loading your whole application
  12. # just for the purpose of running a single test. If you are using a tool that
  13. # preloads Rails for running tests, you may have to set it to true.
  14. 1 config.eager_load = false
  15. # Configure public file server for tests with Cache-Control for performance.
  16. 1 config.public_file_server.enabled = true
  17. 1 config.public_file_server.headers = {
  18. 'Cache-Control' => 'public, max-age=3600'
  19. }
  20. # Show full error reports and disable caching.
  21. 1 config.consider_all_requests_local = true
  22. 1 config.action_controller.perform_caching = false
  23. # Raise exceptions instead of rendering exception templates.
  24. 1 config.action_dispatch.show_exceptions = false
  25. # Disable request forgery protection in test environment.
  26. 1 config.action_controller.allow_forgery_protection = false
  27. 1 config.action_mailer.perform_caching = false
  28. # Tell Action Mailer not to deliver emails to the real world.
  29. # The :test delivery method accumulates sent emails in the
  30. # ActionMailer::Base.deliveries array.
  31. 1 config.action_mailer.delivery_method = :test
  32. # Print deprecation notices to the stderr.
  33. 1 config.active_support.deprecation = :stderr
  34. # Raises error for missing translations
  35. # config.action_view.raise_on_missing_translations = true
  36. 1 config.notification_email = 'fake@sample.com'
  37. end

config/features.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. 1 Flipflop.configure do
  2. 1 feature :only_use_data_set_work_type,
  3. default: true,
  4. description: "Only give users ability to create Data Set Work Type"
  5. 1 feature :limit_browse_options,
  6. default: true,
  7. description: "Limit the users browse options"
  8. 1 feature :dir_upload,
  9. default: false,
  10. description: "Allow user to upload files for work from a directory."
  11. end

config/initializers/application_controller_renderer.rb

100.0% lines covered

0 relevant lines. 0 lines covered and 0 lines missed.
    
  1. # Be sure to restart your server when you modify this file.
  2. # ApplicationController.renderer.defaults.merge!(
  3. # http_host: 'example.org',
  4. # https: false
  5. # )

config/initializers/assets.rb

100.0% lines covered

1 relevant lines. 1 lines covered and 0 lines missed.
    
  1. # Be sure to restart your server when you modify this file.
  2. # Version of your assets, change this if you want to expire all your assets.
  3. 1 Rails.application.config.assets.version = '1.0'
  4. # Add additional assets to the asset load path
  5. # Rails.application.config.assets.paths << Emoji.images_path
  6. # Precompile additional assets.
  7. # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
  8. # Rails.application.config.assets.precompile += %w( search.js )

config/initializers/backtrace_silencers.rb

100.0% lines covered

0 relevant lines. 0 lines covered and 0 lines missed.
    
  1. # Be sure to restart your server when you modify this file.
  2. # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
  3. # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
  4. # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
  5. # Rails.backtrace_cleaner.remove_silencers!

config/initializers/bulkrax.rb

100.0% lines covered

3 relevant lines. 3 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 Bulkrax.setup do |config|
  3. # Add local parsers
  4. # config.parsers += [
  5. # { name: 'MODS - My Local MODS parser', class_name: 'Bulkrax::ModsXmlParser', partial: 'mods_fields' },
  6. # ]
  7. # Field to use during import to identify if the Work or Collection already exists.
  8. # Default is 'source'.
  9. # config.system_identifier_field = 'source'
  10. # WorkType to use as the default if none is specified in the import
  11. # Default is the first returned by Hyrax.config.curation_concerns
  12. 1 config.default_work_type = 'DataSet'
  13. # Path to store pending imports
  14. # config.import_path = 'tmp/imports'
  15. # Path to store exports before download
  16. # config.export_path = 'tmp/exports'
  17. # Server name for oai request header
  18. # config.server_name = 'my_server@name.com'
  19. # Field_mapping for establishing the source_identifier
  20. # This value IS NOT used for OAI, so setting the OAI Entries here will have no effect
  21. # The mapping is supplied per Entry, provide the full class name as a string, eg. 'Bulkrax::CsvEntry'
  22. # Example:
  23. # {
  24. # 'Bulkrax::RdfEntry' => 'http://opaquenamespace.org/ns/identifier',
  25. # 'Bulkrax::CsvEntry' => 'MyIdentifierField'
  26. # }
  27. # The default value for CSV is 'source_identifier'
  28. # Field_mapping for establishing a parent-child relationship (FROM parent TO child)
  29. # This can be a Collection to Work, or Work to Work relationship
  30. # This value IS NOT used for OAI, so setting the OAI Entries here will have no effect
  31. # The mapping is supplied per Entry, provide the full class name as a string, eg. 'Bulkrax::CsvEntry'
  32. # Example:
  33. # {
  34. # 'Bulkrax::RdfEntry' => 'http://opaquenamespace.org/ns/contents',
  35. # 'Bulkrax::CsvEntry' => 'children'
  36. # }
  37. # By default no parent-child relationships are added
  38. # config.parent_child_field_mapping = { }
  39. # Field_mapping for establishing a collection relationship (FROM work TO collection)
  40. # This value IS NOT used for OAI, so setting the OAI parser here will have no effect
  41. # The mapping is supplied per Entry, provide the full class name as a string, eg. 'Bulkrax::CsvEntry'
  42. # The default value for CSV is collection
  43. # Add/replace parsers, for example:
  44. # config.collection_field_mapping['Bulkrax::RdfEntry'] = 'http://opaquenamespace.org/ns/set'
  45. # Field mappings
  46. # Create a completely new set of mappings by replacing the whole set as follows
  47. 1 config.field_mappings = {
  48. "Bulkrax::CsvParser" => {
  49. "source" => { from: ["DSpace handle"] },
  50. "title" => { from: ["Title"] },
  51. "creator" => { from: ["Creator"] },
  52. "authoremail" => { from: ["Contact Information"] },
  53. "description_abstract" => { from: ["Abstract"] },
  54. "methodology" => { from: ["Methodology"] },
  55. "description" => { from: ["Description"] },
  56. "date_coverage" => { from: ["Date Coverage"] },
  57. "rights_license" => { from: ["License"] },
  58. "discipline" => { from: ["Discipline"] },
  59. "fundedby" => { from: ["Funding Agency"] },
  60. "keyword" => { from: ["Keyword"] },
  61. "language" => { from: ["Language"] },
  62. "referenced_by" => { from: ["Citation to related material"] },
  63. "embargo_reason" => { from: ["Embargo"] },
  64. "doi" => { from: ["DOI"] },
  65. "resource_type" => { from: ["Type"] },
  66. "publisher" => { from: ["Publisher"] },
  67. "geo_location_box" => { from: ["geoLocationBox"] },
  68. "geo_location_place" => { from: ["geoLocationPlace"] },
  69. "curation_notes_user" => { from: ["Curation Note"] }
  70. }
  71. }
  72. # Add to, or change existing mappings as follows
  73. # e.g. to exclude date
  74. # config.field_mappings["Bulkrax::OaiDcParser"]["date"] = { from: ["date"], excluded: true }
  75. # To duplicate a set of mappings from one parser to another
  76. # config.field_mappings["Bulkrax::OaiOmekaParser"] = {}
  77. # config.field_mappings["Bulkrax::OaiDcParser"].each {|key,value| config.field_mappings["Bulkrax::OaiOmekaParser"][key] = value }
  78. # Properties that should not be used in imports/exports. They are reserved for use by Hyrax.
  79. # config.reserved_properties += ['my_field']
  80. end

config/initializers/clamav.rb

57.14% lines covered

7 relevant lines. 4 lines covered and 3 lines missed.
    
  1. # frozen_string_literal: true
  2. # ClamAV.instance.loaddb if defined? ClamAV
  3. 1 if defined? ClamAV && ENV['CI'] != 'true'
  4. 1 require "umich_clamav_daemon_scanner"
  5. 1 Hydra::Works.default_system_virus_scanner = UMichClamAVDaemonScanner
  6. 1 Rails.logger.info "Using ClamAV Daemon virus checker."
  7. else
  8. require "null_virus_scanner"
  9. Hydra::Works.default_system_virus_scanner = NullVirusScanner
  10. Rails.logger.warn "No virus checker in use."
  11. end

config/initializers/config.rb

14.29% lines covered

7 relevant lines. 1 lines covered and 6 lines missed.
    
  1. # Initializer for the Config gem.
  2. 1 Config.setup do |config|
  3. # Name of the constant exposing loaded settings
  4. config.const_name = 'Settings'
  5. # Use ENV settings
  6. config.use_env = true
  7. config.env_prefix = 'DATACORE'
  8. config.env_separator = '__'
  9. config.env_converter = :downcase
  10. config.env_parse_values = true
  11. end

config/initializers/cookies_serializer.rb

100.0% lines covered

1 relevant lines. 1 lines covered and 0 lines missed.
    
  1. # Be sure to restart your server when you modify this file.
  2. # Specify a serializer for the signed and encrypted cookie jars.
  3. # Valid options are :json, :marshal, and :hybrid.
  4. 1 Rails.application.config.action_dispatch.cookies_serializer = :json

config/initializers/devise.rb

100.0% lines covered

17 relevant lines. 17 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'devise/behaviors/http_header_authenticatable_behavior'
  3. 1 require 'devise/strategies/http_header_authenticatable'
  4. 1 require 'devise/models/http_header_authenticatable'
  5. # Use this hook to configure devise mailer, warden hooks and so forth.
  6. # Many of these configuration options can be set straight in your model.
  7. 1 Devise.setup do |config|
  8. # The secret key used by Devise. Devise uses this key to generate
  9. # random tokens. Changing this key will render invalid all existing
  10. # confirmation, reset password and unlock tokens in the database.
  11. # Devise will use the `secret_key_base` as its `secret_key`
  12. # by default. You can change it below and use your own secret key.
  13. # config.secret_key = 'e7911530582fd2cbf68829186c8bec117cc78661bfe9fc3f8f2260fffb032bc1167ca4276dad2270891d2337c5e6b7f164776ac6c7178e9591bc9f2ef4af9590'
  14. # ==> Controller configuration
  15. # Configure the parent class to the devise controllers.
  16. # config.parent_controller = 'DeviseController'
  17. # ==> Mailer Configuration
  18. # Configure the e-mail address which will be shown in Devise::Mailer,
  19. # note that it will be overwritten if you use your own mailer class
  20. # with default "from" parameter.
  21. 1 config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
  22. # Configure the class responsible to send e-mails.
  23. # config.mailer = 'Devise::Mailer'
  24. # Configure the parent class responsible to send e-mails.
  25. # config.parent_mailer = 'ActionMailer::Base'
  26. # ==> ORM configuration
  27. # Load and configure the ORM. Supports :active_record (default) and
  28. # :mongoid (bson_ext recommended) by default. Other ORMs may be
  29. # available as additional gems.
  30. 1 require 'devise/orm/active_record'
  31. # ==> Configuration for any authentication mechanism
  32. # Configure which keys are used when authenticating a user. The default is
  33. # just :email. You can configure it to use [:username, :subdomain], so for
  34. # authenticating a user, both parameters are required. Remember that those
  35. # parameters are used only when authenticating and not when retrieving from
  36. # session. If you need permissions, you should implement that in a before filter.
  37. # You can also supply a hash where the value is a boolean determining whether
  38. # or not authentication should be aborted when the value is not present.
  39. # config.authentication_keys = [:email]
  40. # Configure parameters from the request object used for authentication. Each entry
  41. # given should be a request method and it will automatically be passed to the
  42. # find_for_authentication method and considered in your model lookup. For instance,
  43. # if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
  44. # The same considerations mentioned for authentication_keys also apply to request_keys.
  45. # config.request_keys = []
  46. # Configure which authentication keys should be case-insensitive.
  47. # These keys will be downcased upon creating or modifying a user and when used
  48. # to authenticate or find a user. Default is :email.
  49. 1 config.case_insensitive_keys = [:email]
  50. # Configure which authentication keys should have whitespace stripped.
  51. # These keys will have whitespace before and after removed upon creating or
  52. # modifying a user and when used to authenticate or find a user. Default is :email.
  53. 1 config.strip_whitespace_keys = [:email]
  54. # Tell if authentication through request.params is enabled. True by default.
  55. # It can be set to an array that will enable params authentication only for the
  56. # given strategies, for example, `config.params_authenticatable = [:database]` will
  57. # enable it only for database (email + password) authentication.
  58. # config.params_authenticatable = true
  59. # Tell if authentication through HTTP Auth is enabled. False by default.
  60. # It can be set to an array that will enable http authentication only for the
  61. # given strategies, for example, `config.http_authenticatable = [:database]` will
  62. # enable it only for database authentication. The supported strategies are:
  63. # :database = Support basic authentication with authentication key + password
  64. # config.http_authenticatable = false
  65. # If 401 status code should be returned for AJAX requests. True by default.
  66. # config.http_authenticatable_on_xhr = true
  67. # The realm used in Http Basic Authentication. 'Application' by default.
  68. # config.http_authentication_realm = 'Application'
  69. # It will change confirmation, password recovery and other workflows
  70. # to behave the same regardless if the e-mail provided was right or wrong.
  71. # Does not affect registerable.
  72. # config.paranoid = true
  73. # By default Devise will store the user in session. You can skip storage for
  74. # particular strategies by setting this option.
  75. # Notice that if you are skipping storage for all authentication paths, you
  76. # may want to disable generating routes to Devise's sessions controller by
  77. # passing skip: :sessions to `devise_for` in your config/routes.rb
  78. 1 config.skip_session_storage = [:http_auth]
  79. # By default, Devise cleans up the CSRF token on authentication to
  80. # avoid CSRF token fixation attacks. This means that, when using AJAX
  81. # requests for sign in and sign up, you need to get a new CSRF token
  82. # from the server. You can disable this option at your own risk.
  83. # config.clean_up_csrf_token_on_authentication = true
  84. # When false, Devise will not attempt to reload routes on eager load.
  85. # This can reduce the time taken to boot the app but if your application
  86. # requires the Devise mappings to be loaded during boot time the application
  87. # won't boot properly.
  88. # config.reload_routes = true
  89. # ==> Configuration for :database_authenticatable
  90. # For bcrypt, this is the cost for hashing the password and defaults to 11. If
  91. # using other algorithms, it sets how many times you want the password to be hashed.
  92. #
  93. # Limiting the stretches to just one in testing will increase the performance of
  94. # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
  95. # a value less than 10 in other environments. Note that, for bcrypt (the default
  96. # algorithm), the cost increases exponentially with the number of stretches (e.g.
  97. # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
  98. 1 config.stretches = Rails.env.test? ? 1 : 11
  99. # Set up a pepper to generate the hashed password.
  100. # config.pepper = '58ffcd0df512470b62fbc76b30c5bc61ed67f3e8ca66e184f00727ce8e0e66e54abadafc6286564f3647e7baac353da55723a3a1b7f954f5638eb2e68009d0db'
  101. # Send a notification to the original email when the user's email is changed.
  102. # config.send_email_changed_notification = false
  103. # Send a notification email when the user's password is changed.
  104. # config.send_password_change_notification = false
  105. # ==> Configuration for :confirmable
  106. # A period that the user is allowed to access the website even without
  107. # confirming their account. For instance, if set to 2.days, the user will be
  108. # able to access the website for two days without confirming their account,
  109. # access will be blocked just in the third day. Default is 0.days, meaning
  110. # the user cannot access the website without confirming their account.
  111. # config.allow_unconfirmed_access_for = 2.days
  112. # A period that the user is allowed to confirm their account before their
  113. # token becomes invalid. For example, if set to 3.days, the user can confirm
  114. # their account within 3 days after the mail was sent, but on the fourth day
  115. # their account can't be confirmed with the token any more.
  116. # Default is nil, meaning there is no restriction on how long a user can take
  117. # before confirming their account.
  118. # config.confirm_within = 3.days
  119. # If true, requires any email changes to be confirmed (exactly the same way as
  120. # initial account confirmation) to be applied. Requires additional unconfirmed_email
  121. # db field (see migrations). Until confirmed, new email is stored in
  122. # unconfirmed_email column, and copied to email column on successful confirmation.
  123. 1 config.reconfirmable = true
  124. # Defines which key will be used when confirming an account
  125. # config.confirmation_keys = [:email]
  126. # ==> Configuration for :rememberable
  127. # The time the user will be remembered without asking for credentials again.
  128. # config.remember_for = 2.weeks
  129. # Invalidates all the remember me tokens when the user signs out.
  130. 1 config.expire_all_remember_me_on_sign_out = true
  131. # If true, extends the user's remember period when remembered via cookie.
  132. # config.extend_remember_period = false
  133. # Options to be passed to the created cookie. For instance, you can set
  134. # secure: true in order to force SSL only cookies.
  135. # config.rememberable_options = {}
  136. # ==> Configuration for :validatable
  137. # Range for password length.
  138. 1 config.password_length = 6..128
  139. # Email regex used to validate email formats. It simply asserts that
  140. # one (and only one) @ exists in the given string. This is mainly
  141. # to give user feedback and not to assert the e-mail validity.
  142. 1 config.email_regexp = /\A[^@\s]+@[^@\s]+\z/
  143. # ==> Configuration for :timeoutable
  144. # The time you want to timeout the user session without activity. After this
  145. # time the user will be asked for credentials again. Default is 30 minutes.
  146. # config.timeout_in = 30.minutes
  147. # ==> Configuration for :lockable
  148. # Defines which strategy will be used to lock an account.
  149. # :failed_attempts = Locks an account after a number of failed attempts to sign in.
  150. # :none = No lock strategy. You should handle locking by yourself.
  151. # config.lock_strategy = :failed_attempts
  152. # Defines which key will be used when locking and unlocking an account
  153. # config.unlock_keys = [:email]
  154. # Defines which strategy will be used to unlock an account.
  155. # :email = Sends an unlock link to the user email
  156. # :time = Re-enables login after a certain amount of time (see :unlock_in below)
  157. # :both = Enables both strategies
  158. # :none = No unlock strategy. You should handle unlocking by yourself.
  159. # config.unlock_strategy = :both
  160. # Number of authentication tries before locking an account if lock_strategy
  161. # is failed attempts.
  162. # config.maximum_attempts = 20
  163. # Time interval to unlock the account if :time is enabled as unlock_strategy.
  164. # config.unlock_in = 1.hour
  165. # Warn on the last attempt before the account is locked.
  166. # config.last_attempt_warning = true
  167. # ==> Configuration for :recoverable
  168. #
  169. # Defines which key will be used when recovering the password for an account
  170. # config.reset_password_keys = [:email]
  171. # Time interval you can reset your password with a reset password key.
  172. # Don't put a too small interval or your users won't have the time to
  173. # change their passwords.
  174. 1 config.reset_password_within = 6.hours
  175. # When set to false, does not sign a user in automatically after their password is
  176. # reset. Defaults to true, so a user is signed in automatically after a reset.
  177. # config.sign_in_after_reset_password = true
  178. # ==> Configuration for :encryptable
  179. # Allow you to use another hashing or encryption algorithm besides bcrypt (default).
  180. # You can use :sha1, :sha512 or algorithms from others authentication tools as
  181. # :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20
  182. # for default behavior) and :restful_authentication_sha1 (then you should set
  183. # stretches to 10, and copy REST_AUTH_SITE_KEY to pepper).
  184. #
  185. # Require the `devise-encryptable` gem when using anything other than bcrypt
  186. # config.encryptor = :sha512
  187. # ==> Scopes configuration
  188. # Turn scoped views on. Before rendering "sessions/new", it will first check for
  189. # "users/sessions/new". It's turned off by default because it's slower if you
  190. # are using only default views.
  191. # config.scoped_views = false
  192. # Configure the default scope given to Warden. By default it's the first
  193. # devise role declared in your routes (usually :user).
  194. # config.default_scope = :user
  195. # Set this configuration to false if you want /users/sign_out to sign out
  196. # only the current scope. By default, Devise signs out all scopes.
  197. # config.sign_out_all_scopes = true
  198. # ==> Navigation configuration
  199. # Lists the formats that should be treated as navigational. Formats like
  200. # :html, should redirect to the sign in page when the user does not have
  201. # access, but formats like :xml or :json, should return 401.
  202. #
  203. # If you have any extra navigational formats, like :iphone or :mobile, you
  204. # should add them to the navigational formats lists.
  205. #
  206. # The "*/*" below is required to match Internet Explorer requests.
  207. # config.navigational_formats = ['*/*', :html]
  208. # The default HTTP method used to sign out a resource. Default is :delete.
  209. 1 config.sign_out_via = :get
  210. # ==> OmniAuth
  211. # Add a new OmniAuth provider. Check the wiki for more information on setting
  212. # up on your models and hooks.
  213. # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
  214. # IU AUTH ONLY
  215. 1 config.omniauth :cas,
  216. :host => Settings.omniauth.host,
  217. :login_url => Settings.omniauth.login_url,
  218. :service_validate_url => Settings.omniauth.service_validate_url,
  219. :logout_url => Settings.omniauth.logout_url,
  220. :ssl => true
  221. # ==> Warden configuration
  222. # If you want to use other strategies, that are not supported by Devise, or
  223. # change the failure app, you can configure them inside the config.warden block.
  224. #
  225. # config.warden do |manager|
  226. # manager.intercept_401 = false
  227. # manager.default_strategies(scope: :user).unshift :some_external_strategy
  228. # end
  229. # ==> Mountable engine configurations
  230. # When using Devise inside an engine, let's call it `MyEngine`, and this engine
  231. # is mountable, there are some extra configurations to be taken into account.
  232. # The following options are available, assuming the engine is mounted as:
  233. #
  234. # mount MyEngine, at: '/my_engine'
  235. #
  236. # The router that invoked `devise_for`, in the example above, would be:
  237. # config.router_name = :my_engine
  238. #
  239. # When using OmniAuth, Devise cannot automatically set OmniAuth path,
  240. # so you need to do it manually. For the users scope, it would be:
  241. # config.omniauth_path_prefix = '/my_engine/users/auth'
  242. end

config/initializers/event_logging.rb

100.0% lines covered

2 relevant lines. 2 lines covered and 0 lines missed.
    
  1. # This doesn't seem to do anything
  2. 1 [ :after_create_concern,
  3. :after_create_fileset,
  4. :after_update_content,
  5. :after_revert_content,
  6. :after_update_metadata,
  7. :after_import_local_file_success,
  8. :after_import_local_file_failure,
  9. :after_fixity_check_failure,
  10. :after_destroy,
  11. :after_import_url_success,
  12. :after_import_url_failure
  13. ].each do |event_name|
  14. 11 Deepblue::LoggingService.new event_name: event_name
  15. end

config/initializers/ezid.rb

100.0% lines covered

7 relevant lines. 7 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 Ezid::Client.configure do |config|
  3. 1 config.host = Settings.ezid.host
  4. 1 config.port = Settings.ezid.port
  5. 1 config.user = Settings.ezid.user
  6. 1 config.password = Settings.ezid.password
  7. 1 config.timeout = Settings.ezid.timeout
  8. 1 config.default_shoulder = Settings.ezid.shoulder
  9. end

config/initializers/filter_parameter_logging.rb

100.0% lines covered

1 relevant lines. 1 lines covered and 0 lines missed.
    
  1. # Be sure to restart your server when you modify this file.
  2. # Configure sensitive parameters which will be filtered from the log file.
  3. 1 Rails.application.config.filter_parameters += [:password]

config/initializers/hydra_config.rb

100.0% lines covered

3 relevant lines. 3 lines covered and 0 lines missed.
    
  1. # windows doesn't properly require hydra-head (from the gemfile), so we need to require it explicitly here:
  2. 1 require 'hydra/head' unless defined? Hydra
  3. 1 Hydra.configure do |config|
  4. # This specifies the solr field names of permissions-related fields.
  5. # You only need to change these values if you've indexed permissions by some means other than the Hydra's built-in tooling.
  6. # If you change these, you must also update the permissions request handler in your solrconfig.xml to return those values
  7. #
  8. # config.permissions.discover.group = ActiveFedora::SolrQueryBuilder.solr_name("discover_access_group", :symbol)
  9. # config.permissions.discover.individual = ActiveFedora::SolrQueryBuilder.solr_name("discover_access_person", :symbol)
  10. # config.permissions.read.group = ActiveFedora::SolrQueryBuilder.solr_name("read_access_group", :symbol)
  11. # config.permissions.read.individual = ActiveFedora::SolrQueryBuilder.solr_name("read_access_person", :symbol)
  12. # config.permissions.edit.group = ActiveFedora::SolrQueryBuilder.solr_name("edit_access_group", :symbol)
  13. # config.permissions.edit.individual = ActiveFedora::SolrQueryBuilder.solr_name("edit_access_person", :symbol)
  14. #
  15. # config.permissions.embargo.release_date = ActiveFedora::SolrQueryBuilder.solr_name("embargo_release_date", :stored_sortable, type: :date)
  16. # config.permissions.lease.expiration_date = ActiveFedora::SolrQueryBuilder.solr_name("lease_expiration_date", :stored_sortable, type: :date)
  17. #
  18. #
  19. # Specify the user model
  20. # config.user_model = 'User'
  21. 1 config.user_key_field = Devise.authentication_keys.first
  22. end

config/initializers/hyrax.rb

78.57% lines covered

42 relevant lines. 33 lines covered and 9 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 Hyrax.config do |config|
  3. 1 config.register_curation_concern :data_set
  4. 1 config.register_curation_concern :dissertation
  5. # config.register_curation_concern :generic_work
  6. # Register roles that are expected by your implementation.
  7. # @see Hyrax::RoleRegistry for additional details.
  8. # @note there are magical roles as defined in Hyrax::RoleRegistry::MAGIC_ROLES
  9. # config.register_roles do |registry|
  10. # registry.add(name: 'captaining', description: 'For those that really like the front lines')
  11. # end
  12. # When an admin set is created, we need to activate a workflow.
  13. # The :default_active_workflow_name is the name of the workflow we will activate.
  14. # @see Hyrax::Configuration for additional details and defaults.
  15. # config.default_active_workflow_name = 'default'
  16. # Which RDF term should be used to relate objects to an admin set?
  17. # If this is a new repository, you may want to set a custom predicate term here to
  18. # avoid clashes if you plan to use the default (dct:isPartOf) for other relations.
  19. # config.admin_set_predicate = ::RDF::DC.isPartOf
  20. # Which RDF term should be used to relate objects to a rendering?
  21. # If this is a new repository, you may want to set a custom predicate term here to
  22. # avoid clashes if you plan to use the default (dct:hasFormat) for other relations.
  23. # config.rendering_predicate = ::RDF::DC.hasFormat
  24. # Email recipient of messages sent via the contact form
  25. # config.contact_email = "repo-admin@example.org"
  26. 1 config.contact_email = Settings.hyrax.contact_email
  27. # Text prefacing the subject entered in the contact form
  28. # config.subject_prefix = "Contact form:"
  29. # How many notifications should be displayed on the dashboard
  30. # config.max_notifications_for_dashboard = 5
  31. # How frequently should a file be fixity checked
  32. # config.max_days_between_fixity_checks = 7
  33. # Options to control the file uploader
  34. # Run `bundle exec rake tmp:cache:clear` to clear all the contents of public/assets
  35. # Run `bundle exec rake assets:clobber assets:precompile` in dev for this to take effect
  36. 1 config.uploader = {
  37. limitConcurrentUploads: 6,
  38. maxNumberOfFiles: 100,
  39. # maxFileSize: 500.megabytes
  40. maxFileSize: 2.gigabytes,
  41. url: '/uploads'
  42. }
  43. # Enable displaying usage statistics in the UI
  44. # Defaults to false
  45. # Requires a Google Analytics id and OAuth2 keyfile. See README for more info
  46. 1 config.analytics = false
  47. # Google Analytics tracking ID to gather usage statistics
  48. # config.google_analytics_id = Rails.application.secrets.analytics_id
  49. 1 path = "#{Rails.application.config.paths["config"].existent.first}/analytics_id.yml"
  50. 1 if File.exist? path
  51. Settings.analytics_id ||= Rails.application.config_for(:analytics_id)
  52. config.google_analytics_id = Settings.analytics_id['analytics_id']
  53. else
  54. 1 config.google_analytics_id = nil
  55. end
  56. # Date you wish to start collecting Google Analytic statistics for
  57. # Leaving it blank will set the start date to when ever the file was uploaded by
  58. # NOTE: if you have always sent analytics to GA for downloads and page views leave this commented out
  59. # This is the date on the UMRDR WorkViewStat table record number 1
  60. 1 config.analytic_start_date = DateTime.new(2016, 4, 10 )
  61. # Enables a link to the citations page for a work
  62. # Default is false
  63. 1 config.citations = true
  64. # Where to store tempfiles, leave blank for the system temp directory (e.g. /tmp)
  65. # config.temp_file_base = '/home/developer1'
  66. 1 config.temp_file_base = File.join( Rails.root, 'tmp', 'derivatives') # rubocop:disable Rails/FilePath
  67. # Hostpath to be used in Endnote exports
  68. # config.persistent_hostpath = 'http://localhost/files/'
  69. # If you have ffmpeg installed and want to transcode audio and video set to true
  70. # config.enable_ffmpeg = false
  71. # Hyrax uses NOIDs for files and collections instead of Fedora UUIDs
  72. # where NOID = 10-character string and UUID = 32-character string w/ hyphens
  73. # config.enable_noids = true
  74. # Template for your repository's NOID IDs
  75. # config.noid_template = ".reeddeeddk"
  76. # Use the database-backed minter class
  77. # config.noid_minter_class = Noid::Rails::Minter::Db
  78. # Store identifier minter's state in a file for later replayability
  79. # config.minter_statefile = '/tmp/minter-state'
  80. 1 config.minter_statefile = Settings.hyrax.minter_statefile
  81. # Prefix for Redis keys
  82. # config.redis_namespace = "hyrax"
  83. 1 config.redis_namespace = Settings.hyrax.redis_namespace
  84. # Path to the file characterization tool
  85. # config.fits_path = "fits.sh"
  86. 1 config.fits_path = system("which", "fits.sh") ? "fits.sh" : "/l/local/fits/fits.sh"
  87. # Path to the file derivatives creation tool
  88. # config.libreoffice_path = "soffice"
  89. # Option to enable/disable full text extraction from PDFs
  90. # Default is true, set to false to disable full text extraction
  91. # config.extract_full_text = true
  92. # How many seconds back from the current time that we should show by default of the user's activity on the user's dashboard
  93. # config.activity_to_show_default_seconds_since_now = 24*60*60
  94. # Hyrax can integrate with Zotero's Arkivo service for automatic deposit
  95. # of Zotero-managed research items.
  96. # config.arkivo_api = false
  97. # Stream realtime notifications to users in the browser
  98. # config.realtime_notifications = true
  99. # Location autocomplete uses geonames to search for named regions
  100. # Username for connecting to geonames
  101. 1 config.geonames_username = ''
  102. # Should the acceptance of the licence agreement be active (checkbox), or
  103. # implied when the save button is pressed? Set to true for active
  104. # The default is true.
  105. # config.active_deposit_agreement_acceptance = true
  106. # Should work creation require file upload, or can a work be created first
  107. # and a file added at a later time?
  108. # The default is true.
  109. 1 config.work_requires_files = false
  110. # Enable IIIF image service. This is required to use the
  111. # UniversalViewer-ified show page
  112. #
  113. # If you have run the riiif generator, an embedded riiif service
  114. # will be used to deliver images via IIIF. If you have not, you will
  115. # need to configure the following other configuration values to work
  116. # with your image server:
  117. #
  118. # * iiif_image_url_builder
  119. # * iiif_info_url_builder
  120. # * iiif_image_compliance_level_uri
  121. # * iiif_image_size_default
  122. #
  123. # Default is false
  124. # config.iiif_image_server = false
  125. # Returns a URL that resolves to an image provided by a IIIF image server
  126. 1 config.iiif_image_url_builder = lambda do |file_id, base_url, size|
  127. Riiif::Engine.routes.url_helpers.image_url(file_id, host: base_url, size: size)
  128. end
  129. # config.iiif_image_url_builder = lambda do |file_id, base_url, size|
  130. # "#{base_url}/downloads/#{file_id.split('/').first}"
  131. # end
  132. # Returns a URL that resolves to an info.json file provided by a IIIF image server
  133. 1 config.iiif_info_url_builder = lambda do |file_id, base_url|
  134. uri = Riiif::Engine.routes.url_helpers.info_url(file_id, host: base_url)
  135. uri.sub(%r{/info\.json\Z}, '')
  136. end
  137. # config.iiif_info_url_builder = lambda do |_, _|
  138. # ""
  139. # end
  140. # Returns a URL that indicates your IIIF image server compliance level
  141. # config.iiif_image_compliance_level_uri = 'http://iiif.io/api/image/2/level2.json'
  142. # Returns a IIIF image size default
  143. # config.iiif_image_size_default = '600,'
  144. # Fields to display in the IIIF metadata section; default is the required fields
  145. # config.iiif_metadata_fields = Hyrax::Forms::WorkForm.required_fields
  146. # Should a button with "Share my work" show on the front page to all users (even those not logged in)?
  147. # config.display_share_button_when_not_logged_in = true
  148. # The user who runs batch jobs. Update this if you aren't using emails
  149. # config.batch_user_key = 'batchuser@example.com'
  150. # The user who runs fixity check jobs. Update this if you aren't using emails
  151. # config.audit_user_key = 'audituser@example.com'
  152. #
  153. # The banner image. Should be 5000px wide by 1000px tall
  154. # config.banner_image = 'https://cloud.githubusercontent.com/assets/92044/18370978/88ecac20-75f6-11e6-8399-6536640ef695.jpg'
  155. # Temporary paths to hold uploads before they are ingested into FCrepo
  156. # These must be lambdas that return a Pathname. Can be configured separately
  157. # config.upload_path = ->() { Rails.root + 'tmp' + 'uploads' }
  158. # config.cache_path = ->() { Rails.root + 'tmp' + 'uploads' + 'cache' }
  159. # Location on local file system where derivatives will be stored
  160. # If you use a multi-server architecture, this MUST be a shared volume
  161. # config.derivatives_path = Rails.root.join('tmp', 'derivatives')
  162. # Should schema.org microdata be displayed?
  163. # config.display_microdata = true
  164. # What default microdata type should be used if a more appropriate
  165. # type can not be found in the locale file?
  166. # config.microdata_default_type = 'http://schema.org/CreativeWork'
  167. # Location on local file system where uploaded files will be staged
  168. # prior to being ingested into the repository or having derivatives generated.
  169. # If you use a multi-server architecture, this MUST be a shared volume.
  170. # config.working_path = Rails.root.join( 'tmp', 'uploads')
  171. # Should the media display partial render a download link?
  172. # config.display_media_download_link = true
  173. # A configuration point for changing the behavior of the license service
  174. # @see Hyrax::LicenseService for implementation details
  175. # config.license_service_class = Hyrax::LicenseService
  176. # Labels for display of permission levels
  177. # config.permission_levels = { "View/Download" => "read", "Edit access" => "edit" }
  178. # Labels for permission level options used in dropdown menus
  179. # config.permission_options = { "Choose Access" => "none", "View/Download" => "read", "Edit" => "edit" }
  180. # Labels for owner permission levels
  181. # config.owner_permission_levels = { "Edit Access" => "edit" }
  182. # Path to the ffmpeg tool
  183. # config.ffmpeg_path = 'ffmpeg'
  184. # Max length of FITS messages to display in UI
  185. # config.fits_message_length = 5
  186. # ActiveJob queue to handle ingest-like jobs
  187. # config.ingest_queue_name = :default
  188. 1 config.ingest_queue_name = :ingest
  189. ## Attributes for the lock manager which ensures a single process/thread is mutating a ore:Aggregation at once.
  190. # How many times to retry to acquire the lock before raising UnableToAcquireLockError
  191. # config.lock_retry_count = 600 # Up to 2 minutes of trying at intervals up to 200ms
  192. #
  193. # Maximum wait time in milliseconds before retrying. Wait time is a random value between 0 and retry_delay.
  194. # config.lock_retry_delay = 200
  195. #
  196. # How long to hold the lock in milliseconds
  197. # config.lock_time_to_live = 60_000
  198. ## Do not alter unless you understand how ActiveFedora handles URI/ID translation
  199. # config.translate_id_to_uri = lambda do |uri|
  200. # baseparts = 2 + [(Noid::Rails::Config.template.gsub(/\.[rsz]/, '').length.to_f / 2).ceil, 4].min
  201. # uri.to_s.sub(baseurl, '').split('/', baseparts).last
  202. # end
  203. # config.translate_uri_to_id = lambda do |id|
  204. # "#{ActiveFedora.fedora.host}#{ActiveFedora.fedora.base_path}/#{Noid::Rails.treeify(id)}"
  205. # end
  206. ## Fedora import/export tool
  207. #
  208. # Path to the Fedora import export tool jar file
  209. # config.import_export_jar_file_path = "tmp/fcrepo-import-export.jar"
  210. #
  211. # Location where BagIt files should be exported
  212. # config.bagit_dir = "tmp/descriptions"
  213. # This enables or disables the ability to download files.
  214. 1 config.define_singleton_method(:download_files) do
  215. return true
  216. end
  217. # If browse-everything has been configured, load the configs. Otherwise, set to nil.
  218. begin
  219. 1 if defined? BrowseEverything
  220. 1 config.browse_everything = BrowseEverything.config
  221. else
  222. Rails.logger.warn "BrowseEverything is not installed"
  223. end
  224. rescue Errno::ENOENT
  225. config.browse_everything = nil
  226. end
  227. ## Whitelist all directories which can be used to ingest from the local file
  228. # system.
  229. #
  230. # Any file, and only those, that is anywhere under one of the specified
  231. # directories can be used by CreateWithRemoteFilesActor to add local files
  232. # to works. Files uploaded by the user are handled separately and the
  233. # temporary directory for those need not be included here.
  234. #
  235. # Default value includes BrowseEverything.config['file_system'][:home] if it
  236. # is set, otherwise default is an empty list. You should only need to change
  237. # this if you have custom ingestions using CreateWithRemoteFilesActor to
  238. # ingest files from the file system that are not part of the BrowseEverything
  239. # mount point.
  240. #
  241. # config.whitelisted_ingest_dirs = []
  242. # rubocop#:disable Rails/Output
  243. # Doing this before adding actors freezes the stack
  244. # # print out the actor stack
  245. # actor = Hyrax::CurationConcern.actor
  246. # puts "Hyrax::CurationConcern.actor stack"
  247. # loop do
  248. # puts "actor: #{actor.class.name}"
  249. # break if actor.nil?
  250. # break unless actor.respond_to? :next_actor
  251. # actor = actor.next_actor
  252. # end
  253. # see Hyrax::DefaultMiddlewareStack.build_stack
  254. 1 Hyrax::CurationConcern.actor_factory.insert_after Hyrax::Actors::OptimisticLockValidator, Hyrax::Actors::AfterOptimisticLockValidator
  255. 1 Hyrax::CurationConcern.actor_factory.insert_after Hyrax::Actors::CollectionsMembershipActor, Hyrax::Actors::BeforeAddToWorkActor
  256. 1 Hyrax::CurationConcern.actor_factory.insert_after Hyrax::Actors::AddToWorkActor, Hyrax::Actors::BeforeAttachMembersActor
  257. 1 Hyrax::CurationConcern.actor_factory.insert_after Hyrax::Actors::FeaturedWorkActor, Hyrax::Actors::BeforeModelActor
  258. # turn this on to see verify the stack
  259. # actor = Hyrax::CurationConcern.actor
  260. # puts "Hyrax::CurationConcern.actor stack after inserts"
  261. # loop do
  262. # puts "#{actor.class.name}"
  263. # break if actor.nil?
  264. # break unless actor.respond_to? :next_actor
  265. # actor = actor.next_actor
  266. # end
  267. # rubocop#:enable Rails/Output
  268. # override the path used for branding
  269. # the rest of the code assumes that the this path is symlinked to public/branding
  270. 1 config.instance_variable_set( :@branding_path, Rails.root.join( Settings.relative_url_root, 'branding' ) )
  271. end
  272. 1 Date::DATE_FORMATS[:standard] = "%m/%d/%Y"
  273. 1 Qa::Authorities::Local.register_subauthority('subjects', 'Qa::Authorities::Local::TableBasedAuthority')
  274. 1 Qa::Authorities::Local.register_subauthority('languages', 'Qa::Authorities::Local::TableBasedAuthority')
  275. 1 Qa::Authorities::Local.register_subauthority('genres', 'Qa::Authorities::Local::TableBasedAuthority')
  276. # set bulkrax default work type to first curation_concern if it isn't already set
  277. 1 if Bulkrax.default_work_type.blank?
  278. Bulkrax.default_work_type = Hyrax.config.curation_concerns.first.to_s
  279. end

config/initializers/hyrax_callbacks.rb

100.0% lines covered

0 relevant lines. 0 lines covered and 0 lines missed.
    
  1. # # These events are triggered by actions within Hyrax Actors
  2. # Hyrax.config.callback.set(:after_create_concern) do |curation_concern, user|
  3. # ContentDepositEventJob.perform_later(curation_concern, user)
  4. # Deepblue::EventHelper.after_create_concern_callback( curation_concern: curation_concern, user: user )
  5. # end
  6. # Hyrax.config.callback.set(:after_create_fileset) do |file_set, user|
  7. # FileSetAttachedEventJob.perform_later(file_set, user)
  8. # Deepblue::EventHelper.after_create_fileset_callback( file_set: file_set, user: user )
  9. # end
  10. # Hyrax.config.callback.set(:after_revert_content) do |file_set, user, revision|
  11. # ContentRestoredVersionEventJob.perform_later(file_set, user, revision)
  12. # Deepblue::EventHelper.after_revert_content_callback( file_set: file_set, user: user )
  13. # end
  14. # # :after_update_content callback replaced by after_perform block in IngestJob
  15. # Hyrax.config.callback.set(:after_update_metadata) do |curation_concern, user|
  16. # ContentUpdateEventJob.perform_later(curation_concern, user)
  17. # Deepblue::EventHelper.after_update_metadata_callback( curation_concern: curation_concern, user: user )
  18. # end
  19. # Hyrax.config.callback.set(:after_destroy) do |id, user|
  20. # ContentDeleteEventJob.perform_later(id, user)
  21. # Deepblue::EventHelper.after_destroy_callback( id: id, user: user )
  22. # end
  23. # Hyrax.config.callback.set(:after_fixity_check_failure) do |file_set, checksum_audit_log:|
  24. # Hyrax::FixityCheckFailureService.new(file_set, checksum_audit_log: checksum_audit_log).call
  25. # Deepblue::EventHelper.after_fixity_check_failure_callback( file_set: file_set, checksum_audit_log: checksum_audit_log )
  26. # end
  27. # Hyrax.config.callback.set(:after_batch_create_success) do |user|
  28. # Hyrax::BatchCreateSuccessService.new(user).call
  29. # Deepblue::EventHelper.after_batch_create_succes_callback( curation_concern: curation_concern, user: user )
  30. # end
  31. # Hyrax.config.callback.set(:after_batch_create_failure) do |user, messages|
  32. # Hyrax::BatchCreateFailureService.new(user, messages).call
  33. # Deepblue::EventHelper.after_batch_create_failure_callback( user: user, msg: messages )
  34. # end
  35. # Hyrax.config.callback.set(:after_import_url_success) do |file_set, user|
  36. # # ImportUrlSuccessService was removed here since it's duplicative of
  37. # # the :after_create_fileset notification
  38. # end
  39. # Hyrax.config.callback.set(:after_import_url_failure) do |file_set, user|
  40. # Hyrax::ImportUrlFailureService.new(file_set, user).call
  41. # Deepblue::EventHelper.after_import_url_failure_callback( file_set: file_set, user: user )
  42. # end

config/initializers/inflections.rb

100.0% lines covered

0 relevant lines. 0 lines covered and 0 lines missed.
    
  1. # Be sure to restart your server when you modify this file.
  2. # Add new inflection rules using the following format. Inflections
  3. # are locale specific, and you may define rules for as many different
  4. # locales as you wish. All of these examples are active by default:
  5. # ActiveSupport::Inflector.inflections(:en) do |inflect|
  6. # inflect.plural /^(ox)$/i, '\1en'
  7. # inflect.singular /^(ox)en/i, '\1'
  8. # inflect.irregular 'person', 'people'
  9. # inflect.uncountable %w( fish sheep )
  10. # end
  11. # These inflection rules are supported but not enabled by default:
  12. # ActiveSupport::Inflector.inflections(:en) do |inflect|
  13. # inflect.acronym 'RESTful'
  14. # end

config/initializers/ldap_groups_lookup.rb

100.0% lines covered

1 relevant lines. 1 lines covered and 0 lines missed.
    
  1. 1 LDAPGroupsLookup.config = {
  2. enabled: Settings.ldap[:enabled],
  3. config: { host: Settings.ldap[:host],
  4. port: Settings.ldap[:port] || 636,
  5. encryption: {
  6. method: :simple_tls,
  7. tls_options: OpenSSL::SSL::SSLContext::DEFAULT_PARAMS,
  8. },
  9. auth: {
  10. method: :simple,
  11. username: "cn=#{Settings.ldap[:user]}",
  12. password: Settings.ldap[:pass],
  13. }
  14. },
  15. tree: Settings.ldap[:tree],
  16. account_ou: Settings.ldap[:account_ou],
  17. group_ou: Settings.ldap[:group_ou]
  18. }

config/initializers/mailboxer.rb

100.0% lines covered

10 relevant lines. 10 lines covered and 0 lines missed.
    
  1. 1 Mailboxer.setup do |config|
  2. #Configures if your application uses or not email sending for Notifications and Messages
  3. 1 config.uses_emails = true
  4. #Configures the default from for emails sent for Messages and Notifications
  5. 1 config.default_from = "no-reply@mailboxer.com"
  6. #Configures the methods needed by mailboxer
  7. 1 config.email_method = :mailboxer_email
  8. 1 config.name_method = :name
  9. 1 config.notify_method = :notify
  10. #Configures if you use or not a search engine and which one you are using
  11. #Supported engines: [:solr,:sphinx,:pg_search]
  12. 1 config.search_enabled = false
  13. 1 config.search_engine = :solr
  14. #Configures maximum length of the message subject and body
  15. 1 config.subject_max_length = 255
  16. 1 config.body_max_length = 32000
  17. end

config/initializers/mime_types.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # Be sure to restart your server when you modify this file.
  2. # Add new mime types for use in respond_to blocks:
  3. # Mime::Type.register "text/richtext", :rtf
  4. 1 Mime::Type.register "application/n-triples", :nt
  5. 1 Mime::Type.register "application/ld+json", :jsonld
  6. 1 Mime::Type.register "text/turtle", :ttl
  7. 1 Mime::Type.register 'application/x-endnote-refer', :endnote

config/initializers/mini_magick.rb

100.0% lines covered

3 relevant lines. 3 lines covered and 0 lines missed.
    
  1. 1 require 'mini_magick'
  2. 1 MiniMagick.configure do |config|
  3. 1 config.shell_api = "posix-spawn"
  4. end

config/initializers/new_framework_defaults.rb

100.0% lines covered

5 relevant lines. 5 lines covered and 0 lines missed.
    
  1. # Be sure to restart your server when you modify this file.
  2. #
  3. # This file contains migration options to ease your Rails 5.0 upgrade.
  4. #
  5. # Read the Guide for Upgrading Ruby on Rails for more info on each option.
  6. # Enable per-form CSRF tokens. Previous versions had false.
  7. 1 Rails.application.config.action_controller.per_form_csrf_tokens = true
  8. # Enable origin-checking CSRF mitigation. Previous versions had false.
  9. 1 Rails.application.config.action_controller.forgery_protection_origin_check = true
  10. # Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`.
  11. # Previous versions had false.
  12. 1 ActiveSupport.to_time_preserves_timezone = true
  13. # Require `belongs_to` associations by default. Previous versions had false.
  14. 1 Rails.application.config.active_record.belongs_to_required_by_default = true
  15. # Do not halt callback chains when a callback returns false. Previous versions had true.
  16. # ActiveSupport.halt_callback_chains_on_return_false = false
  17. # Configure SSL options to enable HSTS with subdomains. Previous versions had false.
  18. 1 Rails.application.config.ssl_options = { hsts: { subdomains: true } }

config/initializers/okcomputer.rb

100.0% lines covered

2 relevant lines. 2 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 OkComputer.mount_at = 'status'
  3. 1 OkComputer.logger = Logger.new('log/status.log')

config/initializers/provenance_logging.rb

100.0% lines covered

1 relevant lines. 1 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. # Be sure to restart your server when you modify this file.
  3. 1 DeepBlueDocs::Application.config.after_initialize do
  4. # Rails.logger.info "Initializing provenance logging..."
  5. # STDOUT.puts "Initializing provenance logging..."
  6. # require 'provenance_persistence'
  7. # ActiveFedora::Persistence.prepend( ::Deepblue::ProvenancePersistenceExt )
  8. end

config/initializers/rack_attack.rb

57.14% lines covered

7 relevant lines. 4 lines covered and 3 lines missed.
    
  1. 1 Rack::Attack.enabled = Settings.dig(:rack_attack, :enabled) || false
  2. 1 Rack::Attack.safelist('Safe') do |req|
  3. Datacore::RackAttackConfig.safe_req?(req)
  4. end
  5. 1 Rack::Attack.blocklist('Blocked') do |req|
  6. Datacore::RackAttackConfig.block_req?(req)
  7. end
  8. 1 Rack::Attack.throttle('Throttled',
  9. limit: Settings.dig(:rack_attack, :throttle_limit) || 100,
  10. period: Settings.dig(:rack_attack, :throttle_period) || 2.minutes) do |req|
  11. Datacore::RackAttackConfig.throttle_req?(req)
  12. end

config/initializers/redis_config.rb

100.0% lines covered

2 relevant lines. 2 lines covered and 0 lines missed.
    
  1. 1 require 'redis'
  2. 1 Redis.current = Redis.new(Settings.redis.to_h)

config/initializers/resque_config.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. 1 require 'resque'
  2. # We make another client here with the same options as Redis.current, though
  3. # we may be able to use it directly.
  4. 1 Resque.redis = Redis.new(Settings.redis.to_h)
  5. 1 Resque.redis.namespace = Settings.hyrax.redis_namespace
  6. 1 Resque.inline = Rails.env.test?

config/initializers/riiif.rb

50.0% lines covered

14 relevant lines. 7 lines covered and 7 lines missed.
    
  1. 1 Riiif::Image.file_resolver = Riiif::HTTPFileResolver.new
  2. 1 Riiif::Image.info_service = lambda do |id, _file|
  3. # id will look like a path to a pcdm:file
  4. # (e.g. rv042t299%2Ffiles%2F6d71677a-4f80-42f1-ae58-ed1063fd79c7)
  5. # but we just want the id for the FileSet it's attached to.
  6. # Capture everything before the first slash
  7. fs_id = id.sub(/\A([^\/]*)\/.*/, '\1')
  8. resp = ActiveFedora::SolrService.get("id:#{fs_id}")
  9. doc = resp['response']['docs'].first
  10. raise "Unable to find solr document with id:#{fs_id}" unless doc
  11. { height: doc['height_is'], width: doc['width_is'] }
  12. end
  13. 1 Riiif::Image.file_resolver.id_to_uri = lambda do |id|
  14. ActiveFedora::Base.id_to_uri(CGI.unescape(id)).tap do |url|
  15. Rails.logger.info "Riiif resolved #{id} to #{url}"
  16. end
  17. end
  18. 1 Riiif::Image.authorization_service = Hyrax::IIIFAuthorizationService
  19. 1 Riiif.not_found_image = Rails.root.join('app', 'assets', 'images', 'us_404.svg')
  20. 1 Riiif.unauthorized_image = Rails.root.join('app', 'assets', 'images', 'us_404.svg')
  21. 1 Riiif::Engine.config.cache_duration_in_days = 365

config/initializers/session_store.rb

100.0% lines covered

1 relevant lines. 1 lines covered and 0 lines missed.
    
  1. # Be sure to restart your server when you modify this file.
  2. 1 Rails.application.config.session_store :cookie_store, key: '_deep_blue_docs_session'

config/initializers/simple_form.rb

100.0% lines covered

20 relevant lines. 20 lines covered and 0 lines missed.
    
  1. # NOTE: This is a modified version of simple_form's default config file.
  2. # The only changes were to move the input to after the hint and error.
  3. # Use this setup block to configure all options available in SimpleForm.
  4. 1 SimpleForm.setup do |config|
  5. # Wrappers are used by the form builder to generate a
  6. # complete input. You can remove any component from the
  7. # wrapper, change the order or even add your own to the
  8. # stack. The options given below are used to wrap the
  9. # whole input.
  10. 1 config.wrappers :default, class: :input,
  11. hint_class: :field_with_hint,
  12. error_class: :field_with_errors do |b|
  13. ## Extensions enabled by default
  14. # Any of these extensions can be disabled for a
  15. # given input by passing: `f.input EXTENSION_NAME => false`.
  16. # You can make any of these extensions optional by
  17. # renaming `b.use` to `b.optional`.
  18. # Determines whether to use HTML5 (:email, :url, ...)
  19. # and required attributes
  20. 1 b.use :html5
  21. # Calculates placeholders automatically from I18n
  22. # You can also pass a string as f.input placeholder: "Placeholder"
  23. 1 b.use :placeholder
  24. ## Optional extensions
  25. # They are disabled unless you pass `f.input EXTENSION_NAME => true`
  26. # to the input. If so, they will retrieve the values from the model
  27. # if any exists. If you want to enable any of those
  28. # extensions by default, you can change `b.optional` to `b.use`.
  29. # Calculates maxlength from length validations for string inputs
  30. 1 b.optional :maxlength
  31. # Calculates pattern from format validations for string inputs
  32. 1 b.optional :pattern
  33. # Calculates min and max from length validations for numeric inputs
  34. 1 b.optional :min_max
  35. # Calculates readonly automatically from readonly attributes
  36. 1 b.optional :readonly
  37. ## Inputs
  38. 1 b.use :label
  39. 1 b.use :hint, wrap_with: { tag: :span, class: :hint }
  40. 1 b.use :error, wrap_with: { tag: :span, class: :error }
  41. 1 b.use :input
  42. ## full_messages_for
  43. # If you want to display the full error message for the attribute, you can
  44. # use the component :full_error, like:
  45. #
  46. # b.use :full_error, wrap_with: { tag: :span, class: :error }
  47. end
  48. # The default wrapper to be used by the FormBuilder.
  49. 1 config.default_wrapper = :default
  50. # Define the way to render check boxes / radio buttons with labels.
  51. # Defaults to :nested for bootstrap config.
  52. # inline: input + label
  53. # nested: label > input
  54. 1 config.boolean_style = :nested
  55. # Default class for buttons
  56. 1 config.button_class = 'btn'
  57. # Method used to tidy up errors. Specify any Rails Array method.
  58. # :first lists the first message for each field.
  59. # Use :to_sentence to list all errors for each field.
  60. # config.error_method = :first
  61. # Default tag used for error notification helper.
  62. 1 config.error_notification_tag = :div
  63. # CSS class to add for error notification helper.
  64. 1 config.error_notification_class = 'error_notification'
  65. # ID to add for error notification helper.
  66. # config.error_notification_id = nil
  67. # Series of attempts to detect a default label method for collection.
  68. # config.collection_label_methods = [ :to_label, :name, :title, :to_s ]
  69. # Series of attempts to detect a default value method for collection.
  70. # config.collection_value_methods = [ :id, :to_s ]
  71. # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
  72. # config.collection_wrapper_tag = nil
  73. # You can define the class to use on all collection wrappers. Defaulting to none.
  74. # config.collection_wrapper_class = nil
  75. # You can wrap each item in a collection of radio/check boxes with a tag,
  76. # defaulting to :span.
  77. # config.item_wrapper_tag = :span
  78. # You can define a class to use in all item wrappers. Defaulting to none.
  79. # config.item_wrapper_class = nil
  80. # How the label text should be generated altogether with the required text.
  81. 1 config.label_text = ->(label, required, _) { "#{label} #{required}" }
  82. # You can define the class to use on all labels. Default is nil.
  83. # config.label_class = nil
  84. # You can define the default class to be used on forms. Can be overriden
  85. # with `html: { :class }`. Defaulting to none.
  86. # config.default_form_class = nil
  87. # You can define which elements should obtain additional classes
  88. # config.generate_additional_classes_for = [:wrapper, :label, :input]
  89. # Whether attributes are required by default (or not). Default is true.
  90. # config.required_by_default = true
  91. # Tell browsers whether to use the native HTML5 validations (novalidate form option).
  92. # These validations are enabled in SimpleForm's internal config but disabled by default
  93. # in this configuration, which is recommended due to some quirks from different browsers.
  94. # To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations,
  95. # change this configuration to true.
  96. 1 config.browser_validations = true
  97. # Collection of methods to detect if a file type was given.
  98. # config.file_methods = [ :mounted_as, :file?, :public_filename ]
  99. # Custom mappings for input types. This should be a hash containing a regexp
  100. # to match as key, and the input type that will be used when the field name
  101. # matches the regexp as value.
  102. # config.input_mappings = { /count/ => :integer }
  103. # Custom wrappers for input types. This should be a hash containing an input
  104. # type as key and the wrapper that will be used for all inputs with specified type.
  105. # config.wrapper_mappings = { string: :prepend }
  106. # Namespaces where SimpleForm should look for custom input classes that
  107. # override default inputs.
  108. # config.custom_inputs_namespaces << "CustomInputs"
  109. # Default priority for time_zone inputs.
  110. # config.time_zone_priority = nil
  111. # Default priority for country inputs.
  112. # config.country_priority = nil
  113. # When false, do not use translations for labels.
  114. # config.translate_labels = true
  115. # Automatically discover new inputs in Rails' autoload path.
  116. # config.inputs_discovery = true
  117. # Cache SimpleForm inputs discovery
  118. # config.cache_discovery = !Rails.env.development?
  119. # Default class for inputs
  120. # config.input_class = nil
  121. # Define the default class of the input wrapper of the boolean input.
  122. 1 config.boolean_label_class = 'checkbox'
  123. # Defines if the default input wrapper class should be included in radio
  124. # collection wrappers.
  125. # config.include_default_input_wrapper_class = true
  126. # Defines which i18n scope will be used in Simple Form.
  127. # config.i18n_scope = 'simple_form'
  128. end

config/initializers/simple_form_bootstrap.rb

100.0% lines covered

97 relevant lines. 97 lines covered and 0 lines missed.
    
  1. # NOTE: This is a modified version of simple_form's default config file.
  2. # The only changes were to move the inputs to after the hints and errors.
  3. # Use this setup block to configure all options available in SimpleForm.
  4. 1 SimpleForm.setup do |config|
  5. 1 config.error_notification_class = 'alert alert-danger'
  6. 1 config.button_class = 'btn btn-default'
  7. 1 config.boolean_label_class = nil
  8. 1 config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
  9. 1 b.use :html5
  10. 1 b.use :placeholder
  11. 1 b.optional :maxlength
  12. 1 b.optional :pattern
  13. 1 b.optional :min_max
  14. 1 b.optional :readonly
  15. 1 b.use :label, class: 'control-label'
  16. 1 b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
  17. 1 b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
  18. 1 b.use :input, class: 'form-control'
  19. end
  20. 1 config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
  21. 1 b.use :html5
  22. 1 b.use :placeholder
  23. 1 b.optional :maxlength
  24. 1 b.optional :readonly
  25. 1 b.use :label, class: 'control-label'
  26. 1 b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
  27. 1 b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
  28. 1 b.use :input
  29. end
  30. 1 config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
  31. 1 b.use :html5
  32. 1 b.optional :readonly
  33. 1 b.wrapper tag: 'div', class: 'checkbox' do |ba|
  34. 1 ba.use :label_input
  35. end
  36. 1 b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
  37. 1 b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
  38. end
  39. 1 config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
  40. 1 b.use :html5
  41. 1 b.optional :readonly
  42. 1 b.use :label, class: 'control-label'
  43. 1 b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
  44. 1 b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
  45. 1 b.use :input
  46. end
  47. 1 config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
  48. 1 b.use :html5
  49. 1 b.use :placeholder
  50. 1 b.optional :maxlength
  51. 1 b.optional :pattern
  52. 1 b.optional :min_max
  53. 1 b.optional :readonly
  54. 1 b.use :label, class: 'col-sm-3 control-label'
  55. 1 b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
  56. 1 ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
  57. 1 ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
  58. 1 ba.use :input, class: 'form-control'
  59. end
  60. end
  61. 1 config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
  62. 1 b.use :html5
  63. 1 b.use :placeholder
  64. 1 b.optional :maxlength
  65. 1 b.optional :readonly
  66. 1 b.use :label, class: 'col-sm-3 control-label'
  67. 1 b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
  68. 1 ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
  69. 1 ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
  70. 1 ba.use :input
  71. end
  72. end
  73. 1 config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
  74. 1 b.use :html5
  75. 1 b.optional :readonly
  76. 1 b.wrapper tag: 'div', class: 'col-sm-offset-3 col-sm-9' do |wr|
  77. 1 wr.wrapper tag: 'div', class: 'checkbox' do |ba|
  78. 1 ba.use :label_input
  79. end
  80. 1 wr.use :error, wrap_with: { tag: 'span', class: 'help-block' }
  81. 1 wr.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
  82. end
  83. end
  84. 1 config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
  85. 1 b.use :html5
  86. 1 b.optional :readonly
  87. 1 b.use :label, class: 'col-sm-3 control-label'
  88. 1 b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
  89. 1 ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
  90. 1 ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
  91. 1 ba.use :input
  92. end
  93. end
  94. 1 config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
  95. 1 b.use :html5
  96. 1 b.use :placeholder
  97. 1 b.optional :maxlength
  98. 1 b.optional :pattern
  99. 1 b.optional :min_max
  100. 1 b.optional :readonly
  101. 1 b.use :label, class: 'sr-only'
  102. 1 b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
  103. 1 b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
  104. 1 b.use :input, class: 'form-control'
  105. end
  106. 1 config.wrappers :multi_select, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
  107. 1 b.use :html5
  108. 1 b.optional :readonly
  109. 1 b.use :label, class: 'control-label'
  110. 1 b.wrapper tag: 'div', class: 'form-inline' do |ba|
  111. 1 ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
  112. 1 ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
  113. 1 ba.use :input, class: 'form-control'
  114. end
  115. end
  116. # Wrappers for forms and inputs using the Bootstrap toolkit.
  117. # Check the Bootstrap docs (http://getbootstrap.com)
  118. # to learn about the different styles for forms and inputs,
  119. # buttons and other elements.
  120. 1 config.default_wrapper = :vertical_form
  121. 1 config.wrapper_mappings = {
  122. check_boxes: :vertical_radio_and_checkboxes,
  123. radio_buttons: :vertical_radio_and_checkboxes,
  124. file: :vertical_file_input,
  125. boolean: :vertical_boolean,
  126. datetime: :multi_select,
  127. date: :multi_select,
  128. time: :multi_select
  129. }
  130. end

config/initializers/wrap_parameters.rb

100.0% lines covered

2 relevant lines. 2 lines covered and 0 lines missed.
    
  1. # Be sure to restart your server when you modify this file.
  2. # This file contains settings for ActionController::ParamsWrapper which
  3. # is enabled by default.
  4. # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
  5. 1 ActiveSupport.on_load(:action_controller) do
  6. 2 wrap_parameters format: [:json]
  7. end
  8. # To enable root element in JSON for ActiveRecord objects.
  9. # ActiveSupport.on_load(:active_record) do
  10. # self.include_root_in_json = true
  11. # end

config/routes.rb

93.98% lines covered

83 relevant lines. 78 lines covered and 5 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 resque_web_constraint = lambda do |request|
  3. current_user = request.env['warden'].user
  4. ability = Ability.new current_user
  5. rv = ability.present? && ability.respond_to?(:admin?) && ability.admin?
  6. rv
  7. end
  8. 1 Rails.application.routes.draw do
  9. 1 mount Bulkrax::Engine, at: '/'
  10. 1 mount BrowseEverything::Engine => '/browse'
  11. # block Blacklight bookmark routes
  12. 1 get '/bookmarks', to: 'application#rescue_404'
  13. 1 post '/bookmarks', to: 'application#rescue_404'
  14. 1 get '/bookmarks/*all', to: 'application#rescue_404'
  15. 1 post '/bookmarks/*all', to: 'application#rescue_404'
  16. 1 mount Blacklight::Engine => '/'
  17. 1 get '/concern/generic_works/*rest', to: redirect( '/data/concern/data_sets/%{rest}', status: 302 )
  18. 1 get ':action' => 'hyrax/static#:action', constraints: { action: %r{
  19. about|
  20. agreement|
  21. dbd-documentation-guide|
  22. dbd-glossary|
  23. file-format-preservation|
  24. globus-help|
  25. help|
  26. how-to-upload|
  27. management-plan-text|
  28. mendeley|
  29. metadata-guidance|
  30. prepare-your-data|
  31. retention|
  32. subject_libraries|
  33. support-for-depositors|
  34. terms|
  35. use-downloaded-data|
  36. versions|
  37. zotero
  38. }x },
  39. as: :static
  40. 1 mount Riiif::Engine => 'images', as: :riiif if Hyrax.config.iiif_image_server?
  41. 1 concern :searchable, Blacklight::Routes::Searchable.new
  42. 1 resource :catalog, only: [:index], as: 'catalog', path: '/catalog', controller: 'catalog' do
  43. 1 concerns :searchable
  44. end
  45. 1 if Rails.configuration.authentication_method == "iu"
  46. 1 devise_for :users, controllers: { sessions: 'users/sessions', omniauth_callbacks: "users/omniauth_callbacks" }, skip: [:passwords, :registration]
  47. 1 devise_scope :user do
  48. 1 get('global_sign_out',
  49. to: 'users/sessions#global_logout',
  50. as: :destroy_global_session)
  51. 1 get 'sign_out', to: 'devise/sessions#destroy', as: :destroy_user_session
  52. 1 get 'users/auth/cas', to: 'users/omniauth_authorize#passthru', defaults: { provider: :cas }, as: "new_user_session"
  53. end
  54. else
  55. devise_for :users
  56. end
  57. 1 mount Qa::Engine => '/authorities'
  58. 1 mount Hyrax::Engine, at: '/'
  59. # mount Hydra::RoleManagement::Engine => '/' # uncomment to expose Role management in UI
  60. 1 resources :welcome, only: 'index'
  61. 1 root 'hyrax/homepage#index'
  62. 1 curation_concerns_basic_routes
  63. 1 concern :exportable, Blacklight::Routes::Exportable.new
  64. 1 namespace :hyrax, path: :concern do
  65. 1 resources :collections do
  66. 1 member do
  67. 1 get 'display_provenance_log'
  68. end
  69. end
  70. end
  71. 1 namespace :hyrax, path: :concern do
  72. 1 resources :file_sets do
  73. 1 member do
  74. 1 get 'display_provenance_log'
  75. end
  76. end
  77. end
  78. 1 namespace :hyrax, path: :concern do
  79. 1 resources :data_sets do
  80. 1 member do
  81. # post 'confirm'
  82. 1 get 'display_provenance_log'
  83. 1 get 'doi'
  84. 1 post 'doi'
  85. 1 post 'globus_download'
  86. 1 post 'globus_add_email'
  87. 1 get 'globus_add_email'
  88. 1 delete 'globus_clean_download'
  89. 1 post 'globus_download_add_email'
  90. 1 get 'globus_download_add_email'
  91. 1 post 'globus_download_notify_me'
  92. 1 get 'globus_download_notify_me'
  93. 1 post 'identifiers'
  94. 1 post 'tombstone'
  95. 1 post 'zip_download'
  96. end
  97. end
  98. end
  99. # Permissions routes
  100. 1 namespace :hyrax, path: :concern do
  101. 1 resources :permissions, only: [] do
  102. 1 member do
  103. 1 get :copy_access
  104. end
  105. end
  106. end
  107. 1 resources :solr_documents, only: [:show], path: '/catalog', controller: 'catalog' do
  108. 1 concerns :exportable
  109. end
  110. 1 constraints resque_web_constraint do
  111. 1 mount ResqueWeb::Engine => "/resque"
  112. end
  113. 1 resources :bookmarks do
  114. 1 concerns :exportable
  115. 1 collection do
  116. 1 delete 'clear'
  117. end
  118. end
  119. 1 get '/provenance_log/(:id)', to: 'provenance_log#show'
  120. 1 get '/provenance_log_find/', to: 'provenance_log#show'
  121. 1 post '/provenance_log_find/', to: 'provenance_log#find'
  122. 1 get '/provenance_log_zip_download/', to: 'provenance_log#show'
  123. 1 post '/provenance_log_zip_download/', to: 'provenance_log#log_zip_download'
  124. 1 get '/provenance_log_deleted_works/', to: 'provenance_log#deleted_works'
  125. 1 post '/provenance_log_deleted_works/', to: 'provenance_log#deleted_works'
  126. 1 get '/guest_user_message', to: 'guest_user_message#show'
  127. 1 get '/sda/request/(:collection)/(:object)', to: 'archive#download_request'
  128. 1 get '/sda/status/(:collection)/(:object)', to: 'archive#status'
  129. 1 match '/sda/request/:collection/:object', to: 'archive#download_request', constraints: { object: /[^\/]+/ }, via: :get
  130. # robots.txt and rack attack config forms
  131. 1 resource :robots, only: [:show, :edit, :update]
  132. 1 resource :rack_attack, only: [:edit, :update]
  133. # Send ActionController::RoutingError to 404 page
  134. # Must be the last route defined
  135. 1 match '*unmatched', to: 'application#rescue_404', via: :all
  136. # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  137. end

config/spring.rb

100.0% lines covered

2 relevant lines. 2 lines covered and 0 lines missed.
    
  1. %w(
  2. 1 .ruby-version
  3. .rbenv-vars
  4. tmp/restart.txt
  5. tmp/caching-dev.txt
  6. 4 ).each { |path| Spring.watch(path) }

lib/abstract_virus_scanner.rb

46.15% lines covered

13 relevant lines. 6 lines covered and 7 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class AbstractVirusScanner < Hydra::Works::VirusScanner
  3. 1 def initialize( file )
  4. 6 super( file )
  5. end
  6. 1 def clam_av_scanner
  7. scan_result = ClamAV.instance.method(:scanfile).call(file)
  8. return ::Deepblue::VirusScanService::VIRUS_SCAN_NOT_VIRUS if scan_result.zero?
  9. warning "A virus was found in #{file}: #{scan_result}"
  10. ::Deepblue::VirusScanService::VIRUS_SCAN_VIRUS
  11. end
  12. 1 def infected?
  13. ::Deepblue::VirusScanService::VIRUS_SCAN_SKIPPED
  14. end
  15. 1 def null_scanner
  16. warning "Unable to check #{file} for viruses because no virus scanner is defined"
  17. ::Deepblue::VirusScanService::VIRUS_SCAN_SKIPPED_SERVICE_UNAVAILABLE
  18. end
  19. end

lib/active_fedora/persistence.rb

35.71% lines covered

126 relevant lines. 45 lines covered and 81 lines missed.
    
  1. # frozen_string_literal: true
  2. # monkey patch of active_fedora gem, lib/active_fedora/persistence.rb
  3. 1 module ActiveFedora
  4. # = Active Fedora Persistence
  5. 1 module Persistence
  6. 1 extend ActiveSupport::Concern
  7. 1 def new_record?
  8. 358 return true if @ldp_source.subject.nil?
  9. 16 @ldp_source.get
  10. false
  11. rescue Ldp::Gone
  12. false
  13. rescue Ldp::NotFound
  14. true
  15. end
  16. 1 def persisted?
  17. 65 !(destroyed? || new_record?)
  18. end
  19. # Returns true if this object has been destroyed, otherwise returns false.
  20. 1 def destroyed?
  21. 65 @destroyed
  22. end
  23. # Saves a Base object, and any dirty attached files, then updates
  24. # the Solr index for this object, unless option :update_index=>false is present.
  25. # Indexing is also controlled by the `create_needs_index?' and `update_needs_index?' methods.
  26. #
  27. # @param [Hash] options
  28. # @option options [Boolean] :update_index (true) set false to skip indexing
  29. # @return [Boolean] true if save was successful, otherwise false
  30. 1 def save(*options)
  31. create_or_update(*options)
  32. end
  33. 1 def save!(*args)
  34. create_or_update(*args)
  35. end
  36. # Pushes the object and all of its new or dirty attached files into Fedora
  37. 1 def update(attributes)
  38. assign_attributes(attributes)
  39. save
  40. end
  41. 1 alias update_attributes update
  42. # Updates its receiver just like #update but calls #save! instead
  43. # of +save+, so an exception is raised if the record is invalid and saving will fail.
  44. 1 def update!(attributes)
  45. assign_attributes(attributes)
  46. save!
  47. end
  48. 1 alias update_attributes! update!
  49. # Deletes an object from Fedora and deletes the indexed record from Solr.
  50. # Delete does not run any callbacks, so consider using _destroy_ instead.
  51. # @param [Hash] opts
  52. # @option opts [Boolean] :eradicate if passed in, eradicate the tombstone from Fedora
  53. 1 def delete(opts = {})
  54. return self if new_record?
  55. @destroyed = true
  56. id = self.id ## cache so it's still available after delete
  57. # Clear out the ETag
  58. @ldp_source = build_ldp_resource(id)
  59. begin
  60. @ldp_source.delete
  61. rescue Ldp::NotFound
  62. raise ObjectNotFoundError, "Unable to find #{id} in the repository"
  63. end
  64. ActiveFedora::SolrService.delete(id) if ActiveFedora.enable_solr_updates?
  65. self.class.eradicate(id) if opts[:eradicate]
  66. freeze
  67. end
  68. # Delete the object from Fedora and Solr. Run any before/after/around callbacks for destroy
  69. # @param [Hash] opts
  70. # @option opts [Boolean] :eradicate if passed in, eradicate the tombstone from Fedora
  71. 1 def destroy(*opts)
  72. raise ReadOnlyRecord if readonly?
  73. delete(*opts)
  74. end
  75. # Deletes the record in the database and freezes this instance to reflect
  76. # that no changes should be made (since they can't be persisted).
  77. #
  78. # There's a series of callbacks associated with #destroy!. If the
  79. # <tt>before_destroy</tt> callback throws +:abort+ the action is cancelled
  80. # and #destroy! raises ActiveFedora::RecordNotDestroyed.
  81. # See ActiveFedora::Callbacks for further details.
  82. 1 def destroy!
  83. destroy || _raise_record_not_destroyed
  84. end
  85. 1 def eradicate
  86. self.class.eradicate(id)
  87. end
  88. # Used when setting containment
  89. 1 def base_path_for_resource=(path)
  90. 71 @base_path = path
  91. end
  92. 1 module ClassMethods
  93. # Creates an object (or multiple objects) and saves it to the repository, if validations pass.
  94. # The resulting object is returned whether the object was saved successfully to the repository or not.
  95. #
  96. # The +attributes+ parameter can be either be a Hash or an Array of Hashes. These Hashes describe the
  97. # attributes on the objects that are to be created.
  98. #
  99. # ==== Examples
  100. # # Create a single new object
  101. # User.create(:first_name => 'Jamie')
  102. #
  103. # # Create an Array of new objects
  104. # User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])
  105. #
  106. # # Create a single object and pass it into a block to set other attributes.
  107. # User.create(:first_name => 'Jamie') do |u|
  108. # u.is_admin = false
  109. # end
  110. #
  111. # # Creating an Array of new objects using a block, where the block is executed for each object:
  112. # User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u|
  113. # u.is_admin = false
  114. # end
  115. 1 def create(attributes = nil, &block)
  116. if attributes.is_a?(Array)
  117. attributes.collect { |attr| create(attr, &block) }
  118. else
  119. object = new(attributes, &block)
  120. object.save
  121. object
  122. end
  123. end
  124. # Removes an object's tombstone so another object with the same uri may be created.
  125. # NOTE: this is in violation of the linked data platform and is only here as a convience
  126. # method. It shouldn't be used in the general course of repository operations.
  127. 1 def eradicate(uri)
  128. gone?(uri) ? delete_tombstone(uri) : false
  129. end
  130. # Allows the user to find out if an id has been used in the system and then been deleted
  131. # @param uri id in fedora that may or may not have been deleted
  132. 1 def gone?(uri)
  133. ActiveFedora::Base.find(uri)
  134. false
  135. rescue Ldp::Gone
  136. true
  137. rescue ActiveFedora::ObjectNotFoundError
  138. false
  139. end
  140. 1 private
  141. 1 def delete_tombstone(uri)
  142. tombstone = ActiveFedora::Base.id_to_uri(uri) + "/fcr:tombstone"
  143. ActiveFedora.fedora.connection.delete(tombstone)
  144. true
  145. end
  146. end
  147. 1 private
  148. 1 def create_or_update(*args)
  149. raise ReadOnlyRecord if readonly?
  150. result = new_record? ? _create_record(*args) : _update_record(*args)
  151. result != false
  152. end
  153. ## begin monkey patch
  154. # Deals with preparing new object to be saved to Fedora, then pushes it and its attached files into Fedora.
  155. 1 def _create_record(_options = {})
  156. assign_rdf_subject
  157. serialize_attached_files
  158. begin
  159. @ldp_source = @ldp_source.create
  160. rescue Ldp::Conflict
  161. _create_record_ldp_source_create_retry
  162. end
  163. assign_uri_to_contained_resources
  164. save_contained_resources
  165. refresh
  166. end
  167. 1 def _create_record_ldp_source_create_retry
  168. # puts ">>>>>>>>>>>>>>>> _create_record_ldp_source_create_retry <<<<<<<<<<<<<<<<<<<<<"
  169. attempts = 0
  170. loop do
  171. break if attempts > 99
  172. new_id = assign_id
  173. # puts ">>>>>>>>>>> assign_id=#{assign_id} <<<<<<<<<<<<<"
  174. begin
  175. @ldp_source = LdpResource.new(ActiveFedora.fedora.connection, self.class.id_to_uri(new_id), @resource)
  176. @ldp_source = @ldp_source.create
  177. return
  178. rescue Ldp::Conflict
  179. attempts += 1
  180. raise if attempts > 99
  181. end
  182. end
  183. end
  184. ## end monkey patch
  185. 1 def _update_record(_options = {})
  186. serialize_attached_files
  187. execute_sparql_update
  188. save_contained_resources
  189. refresh
  190. end
  191. 1 def _raise_record_not_destroyed
  192. @_association_destroy_exception ||= nil
  193. raise @_association_destroy_exception || RecordNotDestroyed.new("Failed to destroy the record", self)
  194. ensure
  195. @_association_destroy_exception = nil
  196. end
  197. 1 def refresh
  198. @ldp_source = build_ldp_resource(id)
  199. @resource = nil
  200. end
  201. 1 def execute_sparql_update
  202. change_set = ChangeSet.new(self, resource, changed_attributes.keys)
  203. return true if change_set.empty?
  204. ActiveFedora.fedora.ldp_resource_service.update(change_set, self.class, id)
  205. end
  206. # Override to tie in an ID minting service
  207. 1 def assign_id; end
  208. # This is only used when creating a new record. If the object doesn't have an id
  209. # and assign_id can mint an id for the object, then assign it to the resource.
  210. # Otherwise the resource will have the id assigned by the LDP server
  211. 1 def assign_rdf_subject
  212. @ldp_source = if !id && new_id = assign_id # rubocop:disable Lint/AssignmentInCondition
  213. LdpResource.new(ActiveFedora.fedora.connection, self.class.id_to_uri(new_id), @resource)
  214. else
  215. LdpResource.new(ActiveFedora.fedora.connection, @ldp_source.subject, @resource, base_path_for_resource)
  216. end
  217. end
  218. 1 def base_path_for_resource
  219. @base_path ||= ActiveFedora.fedora.host + default_base_path_for_resource
  220. end
  221. 1 def default_base_path_for_resource
  222. init_root_path if has_uri_prefix?
  223. root_resource_path
  224. end
  225. # Check to see if the :base_path (from fedora.yml) exists in Fedora. If it doesn't exist, then create it.
  226. 1 def init_root_path
  227. path = root_resource_path.gsub(/^\//, "")
  228. ActiveFedora.fedora.connection.head(path)
  229. rescue Ldp::NotFound
  230. ActiveFedora.fedora.connection.put(path, "")
  231. end
  232. 1 def assign_uri_to_contained_resources
  233. contained_resources.each do |name, source|
  234. source.uri = "#{uri}/#{name}"
  235. end
  236. end
  237. 1 def save_contained_resources
  238. contained_resources.changed.each do |_, resource|
  239. resource.save
  240. end
  241. end
  242. 1 def contained_resources
  243. @contained_resources ||= attached_files.merge(contained_rdf_sources)
  244. end
  245. 1 def contained_rdf_sources
  246. @contained_rdf_sources ||=
  247. AssociationHash.new(self, self.class.contained_rdf_source_reflections)
  248. end
  249. end
  250. end

lib/devise/behaviors/http_header_authenticatable_behavior.rb

62.5% lines covered

8 relevant lines. 5 lines covered and 3 lines missed.
    
  1. # this class is specific to UMich authentication only
  2. # Default strategy for signing in a user, based on remote user attribute in headers.
  3. 1 module Devise::Behaviors
  4. 1 module HttpHeaderAuthenticatableBehavior
  5. # Called if the user doesn't already have a rails session cookie
  6. # Remote user needs to be present and not null
  7. 1 def valid_user?(headers)
  8. remote_user = remote_user(headers)
  9. remote_user.present? && remote_user != '(null)@umich.edu'
  10. end
  11. 1 protected
  12. # Remote user is coming back from cosign as uniquename.
  13. # Append @umich.edu to this value to satisfy user model validations
  14. 1 def remote_user(headers)
  15. return "#{headers['HTTP_X_REMOTE_USER']}@umich.edu" if headers['HTTP_X_REMOTE_USER'].present?
  16. return nil
  17. end
  18. end
  19. end

lib/devise/models/http_header_authenticatable.rb

100.0% lines covered

7 relevant lines. 7 lines covered and 0 lines missed.
    
  1. # this class is specific to UMich authentication only
  2. 1 require 'devise/strategies/http_header_authenticatable'
  3. 1 module Devise
  4. 1 module Models
  5. 1 module HttpHeaderAuthenticatable
  6. 1 extend ActiveSupport::Concern
  7. 1 def after_database_authentication
  8. end
  9. 1 protected
  10. end
  11. end
  12. end

lib/devise/strategies/http_header_authenticatable.rb

41.18% lines covered

17 relevant lines. 7 lines covered and 10 lines missed.
    
  1. # this class is specific to UMich authentication only
  2. 1 module Devise
  3. 1 module Strategies
  4. 1 class HttpHeaderAuthenticatable < ::Devise::Strategies::Base
  5. 1 include Devise::Behaviors::HttpHeaderAuthenticatableBehavior
  6. # Called if the user doesn't already have a rails session cookie
  7. 1 def valid?
  8. valid_user?(request.headers)
  9. end
  10. 1 def authenticate!
  11. user = remote_user(request.headers)
  12. if user.present?
  13. Rails.logger.debug "[AUTHN] HttpHeaderAuthenticatable#authenticate! succeeded: #{user}"
  14. u = User.find_by_user_key(user)
  15. if u.nil?
  16. u = User.create(email: user)
  17. end
  18. success!(u)
  19. else
  20. Rails.logger.debug '[AUTHN] HttpHeaderAuthenticatable#authenticate! failed.'
  21. fail!
  22. end
  23. end
  24. end
  25. end
  26. end
  27. 1 Warden::Strategies.add(:http_header_authenticatable, Devise::Strategies::HttpHeaderAuthenticatable)

lib/email_logger.rb

83.33% lines covered

6 relevant lines. 5 lines covered and 1 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class EmailLogger < Logger
  3. 1 def format_message( _severity, _timestamp, _progname, msg )
  4. "#{msg}\n"
  5. end
  6. end
  7. # don't forget to request log roll-over script to not roll these files over
  8. 1 logfile = File.open( Rails.root.join( 'log', "email_#{Rails.env}.log" ), 'a' ) # create log file
  9. 1 logfile.sync = true # automatically flushes data to file
  10. 1 EMAIL_LOGGER = EmailLogger.new( logfile ) # constant accessible anywhere

lib/extensions/active_fedora/file/escaping_obsoletions.rb

62.5% lines covered

8 relevant lines. 5 lines covered and 3 lines missed.
    
  1. 1 module Extensions
  2. 1 module ActiveFedora
  3. 1 module File
  4. 1 module EscapingObsoletions
  5. # modified from active_fedora: update obsolete URI methods to CGI
  6. 1 def ldp_headers
  7. headers = { 'Content-Type'.freeze => mime_type, 'Content-Length'.freeze => content.size.to_s }
  8. headers['Content-Disposition'.freeze] = "attachment; filename=\"#{::CGI.escape(@original_name)}\"" if @original_name
  9. headers
  10. end
  11. end
  12. end
  13. end
  14. end

lib/extensions/extensions.rb

100.0% lines covered

8 relevant lines. 8 lines covered and 0 lines missed.
    
  1. # extensions.rb - loads monkeypatches for samvera libraries
  2. # handle downloads from fedora, archive server storage
  3. 1 Hyrax::DownloadsController.prepend Extensions::Hyrax::DownloadsController::VariableDownloadSourcing
  4. # update obsolete URI escaping methods
  5. 1 Hydra::AccessControls::Permission.prepend Extensions::Hydra::AccessControls::Permission::EscapingObsoletions
  6. 1 ActiveFedora::File.prepend Extensions::ActiveFedora::File::EscapingObsoletions
  7. # Collections search
  8. 1 Qa::Authorities::Collections.prepend Extensions::Qa::Authorities::Collections::CollectionsSearch
  9. # return false for render_bookmarks_control? in CollectionsController
  10. 1 Hyrax::CollectionsController.prepend Extensions::Hyrax::CollectionsController::RenderBookmarksControl
  11. 1 Hyrax::My::CollectionsController.prepend Extensions::Hyrax::CollectionsController::RenderBookmarksControl
  12. # Statistics By Date Report page
  13. 1 Hyrax::AdminStatsPresenter.prepend Extensions::Hyrax::AdminStatsPresenter::AdminStatsPresenterBehavior
  14. # accessibility improvements
  15. 1 Hyrax::CollapsableSectionPresenter.prepend Extensions::Hyrax::CollapsableSectionPresenter::CollapsableSectionPresenterBehavior

lib/extensions/hydra/access_controls/permission/escaping_obsoletions.rb

100.0% lines covered

9 relevant lines. 9 lines covered and 0 lines missed.
    
  1. 1 module Extensions
  2. 1 module Hydra
  3. 1 module AccessControls
  4. 1 module Permission
  5. 1 module EscapingObsoletions
  6. # modified to use CGI method instead of obsolete URI method
  7. 1 def agent_name
  8. 70 ::CGI.unescape(parsed_agent.last)
  9. end
  10. # modified to use CGI method instead of obsolete URI method
  11. 1 def build_agent_resource(prefix, name)
  12. 71 [::Hydra::AccessControls::Agent.new(::RDF::URI.new("#{prefix}##{::CGI.escape(name)}"))]
  13. end
  14. end
  15. end
  16. end
  17. end
  18. end

lib/extensions/hyrax/admin_stats_presenter/admin_stats_presenter_behavior.rb

100.0% lines covered

12 relevant lines. 12 lines covered and 0 lines missed.
    
  1. 1 module Extensions
  2. 1 module Hyrax
  3. 1 module AdminStatsPresenter
  4. 1 module AdminStatsPresenterBehavior
  5. 1 def valid_dates
  6. 6 start_date.nil? || start_date <= second_date
  7. end
  8. 1 def second_date
  9. 6 end_date || Date.current
  10. end
  11. 1 def clear_invalid_dates!
  12. 2 if start_date && start_date > second_date
  13. 1 stats_filters[:start_date] = nil
  14. 1 stats_filters[:end_date] = nil
  15. end
  16. end
  17. end
  18. end
  19. end
  20. end

lib/extensions/hyrax/collapsable_section_presenter/collapsable_section_presenter_behavior.rb

100.0% lines covered

8 relevant lines. 8 lines covered and 0 lines missed.
    
  1. # modified from hyrax 2.9.6: added aria-label attribute
  2. 1 module Extensions
  3. 1 module Hyrax
  4. 1 module CollapsableSectionPresenter
  5. 1 module CollapsableSectionPresenterBehavior
  6. 1 private
  7. 1 def button_tag
  8. 2 content_tag(:a,
  9. role: 'button',
  10. class: "#{button_class}collapse-toggle",
  11. data: { toggle: 'collapse' },
  12. href: "##{id}",
  13. 'aria-label' => "Expand / Collapse #{text}",
  14. 'aria-expanded' => open,
  15. 'aria-controls' => id) do
  16. 2 safe_join([content_tag(:span, '', class: icon_class, 'aria-hidden' => true),
  17. content_tag(:span, text)], ' ')
  18. end
  19. end
  20. end
  21. end
  22. end
  23. end

lib/extensions/hyrax/collections_controller/render_bookmarks_control.rb

100.0% lines covered

7 relevant lines. 7 lines covered and 0 lines missed.
    
  1. 1 module Extensions
  2. 1 module Hyrax
  3. 1 module CollectionsController
  4. 1 module RenderBookmarksControl
  5. 1 protected
  6. # disable the bookmark control from displaying in gallery view
  7. 1 def render_bookmarks_control?
  8. 2 false
  9. end
  10. end
  11. end
  12. end
  13. end

lib/extensions/hyrax/downloads_controller/variable_download_sourcing.rb

45.45% lines covered

11 relevant lines. 5 lines covered and 6 lines missed.
    
  1. # modified from hyrax for bypass_fedora case
  2. 1 module Extensions
  3. 1 module Hyrax
  4. 1 module DownloadsController
  5. 1 module VariableDownloadSourcing
  6. # Render the 404 page if the file doesn't exist.
  7. # Otherwise renders the file.
  8. 1 def show
  9. case file
  10. when ::ActiveFedora::File
  11. case file.mime_type
  12. when /access-type=URL/
  13. # for original files that bypass fedora, manage archival file interactions on FileSet show page
  14. redirect_to "/concern/file_sets/#{file.id.split('/').first}"
  15. else
  16. # For original files that are stored in fedora
  17. super
  18. end
  19. when ::String
  20. # For derivatives stored on the local file system
  21. send_local_content
  22. else
  23. render_404
  24. end
  25. end
  26. end
  27. end
  28. end
  29. end

lib/extensions/qa/authorities/collections/collections_search.rb

37.5% lines covered

16 relevant lines. 6 lines covered and 10 lines missed.
    
  1. # modified from hyrax 2.9.6
  2. 1 module Extensions
  3. 1 module Qa
  4. 1 module Authorities
  5. 1 module Collections
  6. 1 module CollectionsSearch
  7. 1 def search(_q, controller)
  8. # The Hyrax::CollectionSearchBuilder expects a current_user
  9. return [] unless controller.current_user
  10. repo = ::CatalogController.new.repository
  11. # line below facilitates searching on partial word match
  12. controller.params[:q] << '*' if controller.params[:q].to_s.size >= 2
  13. builder = search_builder(controller)
  14. response = repo.search(builder)
  15. docs = response.documents
  16. docs.map do |doc|
  17. id = doc.id
  18. title = doc.title
  19. { id: id, label: title, value: id }
  20. end
  21. end
  22. end
  23. end
  24. end
  25. end
  26. end

lib/hydra/works/models/concerns/file_set/mime_types.rb

58.33% lines covered

24 relevant lines. 14 lines covered and 10 lines missed.
    
  1. # This was taken directly from Sufia's GenericFile::MimeTypes
  2. 1 module Hydra::Works
  3. 1 module MimeTypes
  4. 1 extend ActiveSupport::Concern
  5. 1 def pdf?
  6. self.class.pdf_mime_types.include? mime_type
  7. end
  8. 1 def image?
  9. self.class.image_mime_types.include? mime_type
  10. end
  11. 1 def video?
  12. self.class.video_mime_types.include? mime_type
  13. end
  14. 1 def audio?
  15. self.class.audio_mime_types.include? mime_type
  16. end
  17. 1 def office_document?
  18. self.class.office_document_mime_types.include? mime_type
  19. end
  20. 1 module ClassMethods
  21. 1 def image_mime_types
  22. ['image/png', 'image/jpeg', 'image/jpg', 'image/jp2', 'image/bmp', 'image/gif', 'image/tiff']
  23. end
  24. 1 def pdf_mime_types
  25. ['application/pdf']
  26. end
  27. 1 def video_mime_types
  28. ['video/mpeg', 'video/mp4', 'video/webm', 'video/x-msvideo', 'video/avi', 'video/quicktime', 'application/mxf']
  29. end
  30. 1 def audio_mime_types
  31. # audio/x-wave is the mime type that fits 0.6.0 returns for a wav file.
  32. # audio/mpeg is the mime type that fits 0.6.0 returns for an mp3 file.
  33. ['audio/mp3', 'audio/mpeg', 'audio/wav', 'audio/x-wave', 'audio/x-wav', 'audio/ogg']
  34. end
  35. 1 def office_document_mime_types
  36. ['text/plain',
  37. 'text/rtf',
  38. 'application/msword',
  39. 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  40. 'application/vnd.oasis.opendocument.text',
  41. 'application/vnd.ms-excel',
  42. 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  43. 'application/vnd.ms-powerpoint',
  44. 'application/vnd.openxmlformats-officedocument.presentationml.presentation']
  45. end
  46. end
  47. end
  48. end

lib/hydra/works/models/concerns/file_set/virus_check.rb

100.0% lines covered

3 relevant lines. 3 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Hydra::Works
  3. 1 module VirusCheck
  4. 1 extend ActiveSupport::Concern
  5. # Move this to Ingest step
  6. # included do
  7. # validate :must_not_detect_viruses
  8. #
  9. # def must_not_detect_viruses
  10. # scan_result = virus_scan
  11. # return true unless virus_scan_detected_virus?( scan_result: scan_result )
  12. # errors.add( :base, "Failed to verify uploaded file is not a virus" )
  13. # false
  14. # end
  15. #
  16. # end
  17. end
  18. end

lib/null_virus_scanner.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'abstract_virus_scanner'
  3. 1 class NullVirusScanner < AbstractVirusScanner
  4. 1 def initialize( file )
  5. 3 super( file )
  6. end
  7. end

lib/provenance_logger.rb

83.33% lines covered

6 relevant lines. 5 lines covered and 1 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class ProvenanceLogger < Logger
  3. 1 def format_message( _severity, _timestamp, _progname, msg )
  4. "#{msg}\n"
  5. end
  6. end
  7. # logfile = File.open("#{Rails.root}/log/custom.log", 'a') # create log file
  8. 1 logfile = File.open( DeepBlueDocs::Application.config.provenance_log_path, 'a' ) # create log file
  9. 1 logfile.sync = true # automatically flushes data to file
  10. 1 PROV_LOGGER = ProvenanceLogger.new( logfile ) # constant accessible anywhere

lib/scheduler_logger.rb

85.71% lines covered

7 relevant lines. 6 lines covered and 1 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 class SchedulerLogger < Logger
  4. 1 def format_message( _severity, _timestamp, _progname, msg )
  5. "#{msg}\n"
  6. end
  7. end
  8. # don't forget to request log roll-over script to not roll these files over
  9. 1 logfile = File.open( Rails.root.join( 'log', "scheduler_#{Rails.env}.log" ), 'a' ) # create log file
  10. 1 logfile.sync = true # automatically flushes data to file
  11. 1 SCHEDULER_LOGGER = SchedulerLogger.new(logfile ) # constant accessible anywhere
  12. end

lib/tasks/abstract_task.rb

50.0% lines covered

26 relevant lines. 13 lines covered and 13 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 require 'tasks/task_logger'
  4. # rubocop:disable Rails/Output
  5. 1 class AbstractTask
  6. 1 DEFAULT_TO_CONSOLE = true
  7. 1 DEFAULT_VERBOSE = false
  8. 1 attr_reader :options
  9. 1 attr_accessor :verbose, :to_console, :logger
  10. 1 def initialize( options: {} )
  11. @options = TaskHelper.task_options_parse options
  12. if @options.key?( :error ) || @options.key?( 'error' )
  13. puts "WARNING: options error #{@options['error']}"
  14. puts "options=#{options}" if @options.key? 'error'
  15. puts "@options=#{@options}" if @options.key? 'error'
  16. end
  17. @to_console = TaskHelper.task_options_value( @options, key: 'to_console', default_value: DEFAULT_VERBOSE )
  18. @verbose = TaskHelper.task_options_value( @options, key: 'verbose', default_value: DEFAULT_VERBOSE )
  19. puts "@verbose=#{@verbose}" if @verbose
  20. end
  21. 1 def logger
  22. @logger ||= logger_initialize
  23. end
  24. 1 def task_msg( msg )
  25. logger.debug msg
  26. puts msg if @to_console
  27. end
  28. 1 def task_options_value( key:, default_value: nil, verbose: false )
  29. TaskHelper.task_options_value( @options, key: key, default_value: default_value, verbose: verbose )
  30. end
  31. 1 protected
  32. 1 def logger_initialize
  33. # TODO: add some flags to the input yml file for log level and Rails logging integration
  34. TaskHelper.logger_new
  35. end
  36. end
  37. # rubocop:enable Rails/Output
  38. end

lib/tasks/task_logger.rb

80.0% lines covered

5 relevant lines. 4 lines covered and 1 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'logger'
  3. 1 module Deepblue
  4. 1 class TaskLogger < Logger
  5. # TODO: add flags for turning on and off parts of message
  6. 1 def format_message( _severity, _timestamp, _progname, msg )
  7. # "#{timestamp.to_formatted_s(:db)} #{severity} User: #{EmailHelper.user_email} #{msg}\n"
  8. "#{msg}\n"
  9. end
  10. end
  11. end

lib/umich_clamav_daemon_scanner.rb

45.71% lines covered

70 relevant lines. 32 lines covered and 38 lines missed.
    
  1. # frozen_string_literal: true
  2. # An AV class that streams the file to an already-running
  3. # clamav daemon
  4. 1 require 'abstract_virus_scanner'
  5. 1 require 'null_virus_scanner'
  6. 1 require 'clamav/client'
  7. 1 class UMichClamAVDaemonScanner < AbstractVirusScanner
  8. # standard umich clamav configuration (from /etc/clamav/clamav.conf)
  9. 1 CONNECTION_TYPE = :tcp
  10. 1 PORT = 3310
  11. 1 MACHINE = '127.0.0.1'
  12. 1 CHUNKSIZE = 4096
  13. 1 class CannotConnectClient < NullVirusScanner
  14. 1 def initialize( file )
  15. 3 super( file )
  16. end
  17. end
  18. 1 attr_accessor :client
  19. 1 def initialize( filename )
  20. 3 super
  21. @client = begin
  22. 3 connection = ClamAV::Connection.new( socket: ::TCPSocket.new('127.0.0.1', 3310),
  23. wrapper: ::ClamAV::Wrappers::NewLineWrapper.new )
  24. ClamAV::Client.new(connection)
  25. rescue Errno::ECONNREFUSED => e # rubocop:disable Lint/UselessAssignment
  26. 3 CannotConnectClient.new( filename )
  27. end
  28. end
  29. # Check to see if we can connect to the configured
  30. # ClamAV daemon
  31. 1 def alive?
  32. 3 case client
  33. when CannotConnectClient
  34. 3 false
  35. else
  36. client.execute( ClamAV::Commands::PingCommand.new )
  37. end
  38. end
  39. 1 def infected?
  40. ::Deepblue::LoggingHelper.bold_debug [ ::Deepblue::LoggingHelper.here,
  41. ::Deepblue::LoggingHelper.called_from,
  42. "UMichClamAVDaemonScanner.infected? File '#{file}' exists? #{File.exist? file}" ]
  43. unless alive?
  44. warning "Cannot connect to virus scanner. Skipping file #{file}"
  45. return ::Deepblue::VirusScanService::VIRUS_SCAN_SKIPPED_SERVICE_UNAVAILABLE
  46. end
  47. resp = scan_response
  48. rv = case resp
  49. when ClamAV::SuccessResponse
  50. info "Clean virus check for '#{file}'"
  51. ::Deepblue::VirusScanService::VIRUS_SCAN_NOT_VIRUS
  52. when ClamAV::VirusResponse
  53. warn "Virus #{resp.virus_name} found in file '#{file}'"
  54. ::Deepblue::VirusScanService::VIRUS_SCAN_VIRUS
  55. when ClamAV::ErrorResponse
  56. warn "ClamAV error: #{resp.error_str} for file #{file}. File not scanned!"
  57. ::Deepblue::VirusScanService::VIRUS_SCAN_ERROR # err on the side of trust? Need to think about this
  58. else
  59. warn "ClamAV response unknown type '#{resp.class}': #{resp}. File not scanned!"
  60. ::Deepblue::VirusScanService::VIRUS_SCAN_UNKNOWN
  61. end
  62. return rv
  63. end
  64. 1 def scan_response
  65. begin
  66. file_io = File.open( file, 'rb' )
  67. rescue => e
  68. msg = "Can't open file #{file} for scanning: #{e}"
  69. error msg
  70. raise msg
  71. end
  72. scan( file_io )
  73. end
  74. # Do the scan by streaming to the daemon
  75. # @param [#read] io The IO stream (probably an open file) to read from
  76. # @return A ClamAV::*Response object
  77. 1 def scan(io)
  78. cmd = UMInstreamScanner.new(io, CHUNKSIZE)
  79. client.execute(cmd)
  80. end
  81. 1 private
  82. # Set up logging for the clamav daemon scanner
  83. 1 def debug( msg )
  84. Hyrax.logger&.debug( msg )
  85. end
  86. 1 def error( msg )
  87. Hyrax.logger&.error( msg )
  88. end
  89. 1 def info( msg )
  90. Hyrax.logger&.info( msg )
  91. end
  92. 1 def warning( msg )
  93. Hyrax.logger&.warn( msg )
  94. end
  95. end
  96. # Stream a file to the AV scanner in chucks to avoid
  97. # reading it all into memory. Internal to how
  98. # ClamAV::Client works
  99. 1 class UMInstreamScanner < ClamAV::Commands::InstreamCommand
  100. 1 def call(conn)
  101. conn.write_request("INSTREAM")
  102. while (packet = @io.read(@max_chunk_size))
  103. scan_packet(conn, packet)
  104. end
  105. send_end_of_file(conn)
  106. av_return_status(conn)
  107. rescue => e
  108. ClamAV::ErrorResponse.new( "Error sending data to ClamAV Daemon: #{e}" )
  109. end
  110. 1 def av_return_status(conn)
  111. get_status_from_response(conn.read_response)
  112. end
  113. 1 def send_end_of_file(conn)
  114. conn.raw_write("\x00\x00\x00\x00")
  115. end
  116. 1 def scan_packet(conn, packet)
  117. packet_size = [packet.size].pack("N")
  118. conn.raw_write("#{packet_size}#{packet}")
  119. end
  120. end
  121. # To use a virus checker other than ClamAV:
  122. # class MyScanner < Hydra::Works::VirusScanner
  123. # def infected?
  124. # my_result = Scanner.check_for_viruses(file)
  125. # [return true or false]
  126. # end
  127. # end

lib/upload_logger.rb

85.71% lines covered

7 relevant lines. 6 lines covered and 1 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 module Deepblue
  3. 1 class UploadLogger < Logger
  4. 1 def format_message( _severity, _timestamp, _progname, msg )
  5. "#{msg}\n"
  6. end
  7. end
  8. # don't forget to request log roll-over script to not roll these files over
  9. 1 logfile = File.open( Rails.root.join( 'log', "upload_#{Rails.env}.log" ), 'a' ) # create log file
  10. 1 logfile.sync = true # automatically flushes data to file
  11. 1 UPLOAD_LOGGER = UploadLogger.new( logfile ) # constant accessible anywhere
  12. end

spec/actors/hyrax/actors/data_set_actor_spec.rb

100.0% lines covered

6 relevant lines. 6 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe Hyrax::Actors::DataSetActor do
  3. 1 let(:work) { DataSet.new }
  4. 1 let(:depositor) { create(:user) }
  5. 1 let(:depositor_ability) { ::Ability.new(depositor) }
  6. 1 let(:env) { Hyrax::Actors::Environment.new(work, depositor_ability, {}) }
  7. # describe '#model_actor' do
  8. # subject { described_class.new('Test').send(:model_actor, env) }
  9. #
  10. # it "preserves the namespacing" do
  11. # is_expected.to be_kind_of Hyrax::Actors::DataSetActor
  12. # end
  13. # end
  14. end

spec/actors/hyrax/actors/dissertation_actor_spec.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work Dissertation`
  3. 1 require 'rails_helper'
  4. 1 RSpec.describe Hyrax::Actors::DissertationActor do
  5. 1 it "has tests" do
  6. 1 skip "Add your tests here"
  7. end
  8. end

spec/actors/hyrax/actors/generic_work_actor_spec.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work GenericWork`
  3. 1 require 'rails_helper'
  4. 1 RSpec.describe Hyrax::Actors::GenericWorkActor do
  5. 1 it "has tests" do
  6. 1 skip "Add your tests here"
  7. end
  8. end

spec/authorities/qa/authorities/collections_spec.rb

75.68% lines covered

37 relevant lines. 28 lines covered and 9 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe Qa::Authorities::Collections do
  3. 1 subject(:service) { described_class.new }
  4. 1 let(:controller) { Qa::TermsController.new }
  5. 7 let(:user1) { FactoryBot.build(:user) }
  6. 1 let!(:collection1) do
  7. 6 FactoryBot.build(:collection_lw,
  8. title: ['foo bar'],
  9. user: user1,
  10. with_solr_document: true)
  11. end
  12. 1 let!(:collection2) do
  13. FactoryBot.build(:collection_lw,
  14. title: ['foo'],
  15. user: user1,
  16. with_solr_document: true)
  17. end
  18. 1 before do
  19. allow(controller).to receive(:params).and_return(params)
  20. allow(controller).to receive(:current_user).and_return(user1)
  21. end
  22. 1 describe '#search' do
  23. 1 context 'with partial starting term' do
  24. 1 let(:params) { ActionController::Parameters.new(q: 'fo') }
  25. 1 it 'lists collection' do
  26. expect(service.search(nil, controller))
  27. .to contain_exactly(include(id: collection1.id), include(id: collection2.id))
  28. end
  29. end
  30. 1 context 'with partial middle term' do
  31. 1 let(:params) { ActionController::Parameters.new(q: 'ba') }
  32. 1 it 'lists collection' do
  33. expect(service.search(nil, controller))
  34. .to contain_exactly(include(id: collection1.id))
  35. end
  36. end
  37. 1 context 'with full term' do
  38. 1 let(:params) { ActionController::Parameters.new(q: 'foo bar') }
  39. 1 it 'lists collection' do
  40. expect(service.search(nil, controller))
  41. .to contain_exactly(include(id: collection1.id))
  42. end
  43. end
  44. 1 context 'with unmatched term' do
  45. 1 let(:params) { ActionController::Parameters.new(q: 'deadbeef') }
  46. 1 it 'lists nothing' do
  47. expect(service.search(nil, controller))
  48. .to match_array ([])
  49. end
  50. end
  51. 1 context 'with too short term' do
  52. 1 let(:params) { ActionController::Parameters.new(q: 'f') }
  53. 1 it 'lists nothing' do
  54. expect(service.search(nil, controller))
  55. .to match_array ([])
  56. end
  57. end
  58. 1 context 'with no term' do
  59. 1 let(:params) { ActionController::Parameters.new() }
  60. 1 it 'lists everything' do
  61. expect(service.search(nil, controller))
  62. .to include(include(id: collection1.id), include(id: collection2.id))
  63. end
  64. end
  65. end
  66. end

spec/controllers/application_controller_spec.rb

100.0% lines covered

50 relevant lines. 50 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe ApplicationController do
  3. 1 describe "#global_request_logging" do
  4. 1 before {
  5. 3 allow(subject).to receive(:request).and_return OpenStruct.new(remote_ip: "1.2.3.4", method: "GET", url: "/", headers: {"HTTP_USER_AGENT" => "agent"})
  6. 3 allow(subject).to receive(:response).and_return OpenStruct.new(status: "responsive")
  7. 3 allow(subject.logger).to receive(:info).with "ACCESS: 1.2.3.4, GET /, agent"
  8. 3 allow(subject.logger).to receive(:info).with "response_status: responsive"
  9. }
  10. 1 context "when called with an empty block" do
  11. 1 it do
  12. 1 expect(subject.logger).to receive(:info).with "ACCESS: 1.2.3.4, GET /, agent"
  13. 1 expect(subject.logger).to receive(:info).with "response_status: responsive"
  14. 1 subject.global_request_logging { }
  15. end
  16. end
  17. 1 context "when called with a block" do
  18. 3 specify { expect { |b| subject.global_request_logging(&b) }.to yield_control }
  19. 3 specify { expect { |b| subject.global_request_logging(&b) }.to yield_with_no_args }
  20. end
  21. end
  22. 1 describe "#clear_session_user" do
  23. 1 context "when called with nil request" do
  24. 1 it "returns nil_request" do
  25. 1 skip "Add a test"
  26. end
  27. end
  28. 1 context "when called with request with value" do
  29. 1 it "clears the session user" do
  30. 1 skip "Add a test"
  31. end
  32. end
  33. end
  34. 1 pending "#after_authentication"
  35. 1 describe "#rescue_404" do
  36. 1 it "renders a not found response" do
  37. 1 get :rescue_404
  38. 1 expect(response.status).to eq 404
  39. end
  40. end
  41. 1 describe "#set_locale" do
  42. 1 context "when locale param is present" do
  43. 1 before {
  44. 2 allow(subject).to receive(:params).and_return "locale" => "italian"
  45. }
  46. 1 context "when constrained_locale has value" do
  47. 1 before {
  48. 1 allow(subject).to receive(:constrained_locale).and_return "english"
  49. }
  50. 1 it "sets locale param to constrained_locale" do
  51. 1 allow(subject).to receive(:params).and_return "locale" => "english"
  52. end
  53. end
  54. 1 context "when I18n.default_locale has value" do
  55. 1 before {
  56. 1 allow(I18n).to receive(:default_locale).and_return "spanish"
  57. }
  58. 1 it "sets locale param to I18n.default_locale" do
  59. 1 allow(subject).to receive(:params).and_return "locale" => "spanish"
  60. end
  61. end
  62. end
  63. 1 context "when locale param is not present" do
  64. 1 it "returns nil" do
  65. 1 expect(subject.set_locale).to be_blank
  66. end
  67. end
  68. end
  69. 1 describe "#constrained_locale" do
  70. 1 context "when locale param in available_translations" do
  71. 1 skip "Add a test"
  72. end
  73. 1 context "when locale not in available_translations" do
  74. 1 skip "Add a test"
  75. end
  76. end
  77. end

spec/controllers/catalog_controller_spec.rb

100.0% lines covered

8 relevant lines. 8 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe CatalogController do
  3. 1 pending "#self.uploaded_field"
  4. 1 pending "#self.modified_field"
  5. 1 pending "configure_blacklight"
  6. 1 describe '#render_bookmarks_control?' do
  7. 1 it 'returns false' do
  8. 1 expect(controller.render_bookmarks_control?).to eq false
  9. end
  10. end
  11. end

spec/controllers/guest_user_message_controller_spec.rb

100.0% lines covered

6 relevant lines. 6 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe GuestUserMessageController do
  3. 1 describe "#show" do
  4. 1 it "renders a response" do
  5. 1 get :show
  6. 1 expect(response.status).to eq 200
  7. end
  8. end
  9. end

spec/controllers/hyrax/collections_controller_spec.rb

90.91% lines covered

11 relevant lines. 10 lines covered and 1 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe Hyrax::CollectionsController do
  3. 2 let(:subject) { described_class.new }
  4. 2 let(:collection) { FactoryBot.create(:collection_lw) }
  5. 1 describe "#render_bookmarks_control?" do
  6. 1 it "returns false" do
  7. 1 expect(subject.send(:render_bookmarks_control?)).to eq false
  8. end
  9. end
  10. 1 describe "#display_provenance_log" do
  11. 1 it "redirects" do
  12. 1 get :display_provenance_log, params: { id: collection.id }
  13. expect(response).to be_redirect
  14. end
  15. end
  16. end

spec/controllers/hyrax/dashboard/collections_controller_spec.rb

100.0% lines covered

148 relevant lines. 148 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 class BannerInfoMock
  3. 1 def initialize local_path
  4. 4 @local_path = local_path
  5. end
  6. 1 def save (path, verify = true)
  7. end
  8. 1 def local_path
  9. 1 @local_path
  10. end
  11. 1 def delete_all
  12. end
  13. end
  14. 1 RSpec.describe Hyrax::Dashboard::CollectionsController do
  15. 16 let(:subject) { described_class.new }
  16. 1 include Hyrax::BrandingHelper
  17. 1 describe 'constants' do
  18. 1 it do
  19. 1 expect( Hyrax::Dashboard::CollectionsController::EVENT_NOTE ).to eq 'Hyrax::Dashboard::CollectionsController'
  20. 1 expect( Hyrax::Dashboard::CollectionsController::PARAMS_KEY ).to eq 'collection'
  21. end
  22. end
  23. 1 describe "#after_create" do
  24. 1 before {
  25. 1 allow(subject).to receive(:monkey_after_create)
  26. 1 allow(subject).to receive(:workflow_create)
  27. }
  28. 1 it "calls monkey_after_create and workflow_create" do
  29. 1 expect(subject).to receive(:monkey_after_create)
  30. 1 expect(subject).to receive(:workflow_create)
  31. 1 subject.after_create
  32. end
  33. end
  34. 1 describe "#destroy" do
  35. 1 before {
  36. 1 allow(subject).to receive(:workflow_destroy)
  37. 1 allow(subject).to receive(:monkey_destroy)
  38. }
  39. 1 it "calls workflow_destroy and monkey_destroy" do
  40. 1 expect(subject).to receive(:workflow_destroy)
  41. 1 expect(subject).to receive(:monkey_destroy)
  42. 1 subject.destroy
  43. end
  44. end
  45. 1 describe "#show" do
  46. 1 before {
  47. 3 allow(subject).to receive(:presenter)
  48. 3 allow(subject).to receive(:query_collection_members)
  49. }
  50. 1 context "when @collection.collection_type.brandable? is true" do
  51. 1 context "when banner_info not empty" do
  52. 1 before {
  53. 1 subject.instance_variable_set(:@collection, OpenStruct.new(id: 63, collection_type: OpenStruct.new( brandable?: true ) ))
  54. 1 allow(subject).to receive(:collection_banner_info).with(id: 63).and_return ["primo", "secundo"]
  55. 1 allow(subject).to receive(:brand_path).with(collection_branding_info: "primo")
  56. }
  57. 1 it "calls collection_banner_info and brand_path" do
  58. 1 expect(subject).to receive(:collection_banner_info).with(id: 63)
  59. 1 expect(subject).to receive(:brand_path)
  60. 1 subject.show
  61. end
  62. end
  63. 1 context "when banner_info empty" do
  64. 1 before {
  65. 1 subject.instance_variable_set(:@collection, OpenStruct.new(id: 36, collection_type: OpenStruct.new( brandable?: true ) ))
  66. 1 allow(subject).to receive(:collection_banner_info).with(id: 36).and_return []
  67. }
  68. 1 it "calls collection_banner_info" do
  69. 1 expect(subject).to receive(:collection_banner_info).with(id: 36)
  70. 1 expect(subject).not_to receive(:brand_path)
  71. 1 subject.show
  72. end
  73. end
  74. end
  75. 1 context "when @collection.collection_type.brandable? is false" do
  76. 1 before {
  77. 1 subject.instance_variable_set(:@collection, OpenStruct.new( collection_type: OpenStruct.new( brandable?: false ) ))
  78. }
  79. 1 it "calls presenter and query_collection_members functions" do
  80. 1 expect(subject).not_to receive(:collection_banner_info)
  81. 1 expect(subject).not_to receive(:brand_path)
  82. 1 subject.show
  83. end
  84. end
  85. 1 after {
  86. 3 expect(subject).to have_received(:presenter)
  87. 3 expect(subject).to have_received(:query_collection_members)
  88. }
  89. end
  90. 1 describe "#curation_concern" do
  91. 1 before {
  92. 2 parameters = { :id => "collectibles" }
  93. 2 allow(subject).to receive(:params).and_return parameters
  94. 2 allow(ActiveFedora::Base).to receive(:find).with("collectibles").and_return "extensive"
  95. }
  96. 1 context "when @collection has value" do
  97. 1 before {
  98. 1 subject.instance_variable_set(:@collection, "collection")
  99. }
  100. 1 it "returns @collection" do
  101. 1 expect(ActiveFedora::Base).not_to receive(:find)
  102. 1 expect(subject.curation_concern).to eq "collection"
  103. end
  104. end
  105. 1 context "when @collection is nil or false" do
  106. 1 it "calls Base.find and sets @collection to the result" do
  107. 1 expect(ActiveFedora::Base).to receive(:find)
  108. 1 expect(subject.curation_concern).to eq "extensive"
  109. 1 subject.instance_variable_get(:@collection) == "extensive"
  110. end
  111. end
  112. end
  113. 1 describe "#default_event_note" do
  114. 1 it "returns string" do
  115. 1 expect(subject.default_event_note).to eq 'Hyrax::Dashboard::CollectionsController'
  116. end
  117. end
  118. 1 describe "#params_key" do
  119. 1 it "returns string" do
  120. 1 expect(subject.params_key).to eq 'collection'
  121. end
  122. end
  123. 1 describe "#process_banner_input" do
  124. 1 before {
  125. 3 allow(subject).to receive(:update_existing_banner).and_return "update: existence"
  126. 3 allow(subject).to receive(:remove_banner)
  127. }
  128. 1 context "when banner_unchanged param true" do
  129. 1 before {
  130. 1 parameters = {"banner_unchanged" => "true"}
  131. 1 allow(subject).to receive(:params).and_return parameters
  132. }
  133. 1 it "returns update_existing_banner" do
  134. 1 expect(subject).not_to receive(:remove_banner)
  135. 1 expect(subject.process_banner_input).to eq "update: existence"
  136. end
  137. end
  138. 1 context "when banner_unchanged param false" do
  139. 1 context "when banner_files param true" do
  140. 1 before {
  141. 1 parameters = {"banner_unchanged" => "false", "banner_files" => true}
  142. 1 allow(subject).to receive(:params).and_return parameters
  143. 1 allow(subject).to receive(:add_new_banner).with(true).and_return "new banner day"
  144. }
  145. 1 it "returns update_existing_banner" do
  146. 1 expect(subject).to receive(:add_new_banner).with(true)
  147. 1 expect(subject.process_banner_input).to eq "new banner day"
  148. end
  149. end
  150. 1 context "when banner_files param false" do
  151. 1 before {
  152. 1 parameters = {"banner_unchanged" => "false", "banner_files" => false}
  153. 1 allow(subject).to receive(:params).and_return parameters
  154. }
  155. 1 it "returns update_existing_banner" do
  156. 1 expect(subject).not_to receive(:add_new_banner)
  157. 1 expect(subject.process_banner_input).to be_blank
  158. end
  159. end
  160. 1 after {
  161. 2 expect(subject).not_to have_received(:update_existing_banner)
  162. 2 expect(subject).to have_received(:remove_banner)
  163. }
  164. end
  165. end
  166. 1 describe "#update_existing_banner" do
  167. 1 banner_info1 = BannerInfoMock.new("path1")
  168. 1 banner_info2 = BannerInfoMock.new("path2")
  169. 1 before {
  170. 1 subject.instance_variable_set(:@collection, OpenStruct.new( id: 3000 ))
  171. 1 allow(subject).to receive(:collection_banner_info).with(id: 3000).and_return [banner_info1, banner_info2]
  172. }
  173. 1 it do
  174. 1 expect(subject).to receive(:collection_banner_info).with( id: 3000 )
  175. 1 expect(banner_info1).to receive(:save).with("path1", false)
  176. 1 subject.update_existing_banner
  177. end
  178. end
  179. 1 describe "#add_new_banner" do
  180. 1 bannerInfo = BannerInfoMock.new "kawaii"
  181. 1 before {
  182. 1 subject.instance_variable_set(:@collection, OpenStruct.new( id: 4000 ))
  183. 1 allow(subject).to receive(:uploaded_files).with("uploaded file ids").and_return [OpenStruct.new(file_url: "kawaii"), OpenStruct.new(file_url: "banzai")]
  184. 1 allow(File).to receive(:split).with("kawaii").and_return ["konnichiwa", "sayonara"]
  185. 1 allow(CollectionBrandingInfo).to receive(:new).with(collection_id: 4000, filename: "sayonara", role: "banner", alt_txt: "", target_url: "")
  186. .and_return bannerInfo
  187. 1 allow(bannerInfo).to receive(:save).with("kawaii")
  188. }
  189. 1 it do
  190. 1 expect(subject).to receive(:uploaded_files).with("uploaded file ids")
  191. 1 expect(CollectionBrandingInfo).to receive(:new).with(collection_id: 4000, filename: "sayonara", role: "banner", alt_txt: "", target_url: "")
  192. 1 expect(bannerInfo).to receive(:save).with("kawaii")
  193. 1 subject.add_new_banner("uploaded file ids")
  194. end
  195. end
  196. 1 describe "#remove_banner" do
  197. 1 bannerInfo = BannerInfoMock.new "a to z"
  198. 1 before {
  199. 1 subject.instance_variable_set(:@collection, OpenStruct.new( id: 5000 ))
  200. 1 allow(subject).to receive(:collection_banner_info).with(id: 5000).and_return bannerInfo
  201. 1 allow(bannerInfo).to receive(:delete_all)
  202. }
  203. 1 it do
  204. 1 expect(subject).to receive(:collection_banner_info).with(id: 5000)
  205. 1 expect(bannerInfo).to receive(:delete_all)
  206. 1 subject.remove_banner
  207. end
  208. end
  209. end

spec/controllers/hyrax/data_sets_controller_spec.rb

90.0% lines covered

10 relevant lines. 9 lines covered and 1 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe Hyrax::DataSetsController do # rubocop:disable RSpec/EmptyExampleGroup
  3. # before(:all ) do
  4. # puts "DataSet ids before=#{DataSet.all.map { |ds| ds.id }}"
  5. # #puts "FileSet ids before=#{FileSet.all.map { |fs| fs.id }}"
  6. # end
  7. #
  8. # after(:all ) do
  9. # #puts "FileSet ids after=#{FileSet.all.map { |fs| fs.id }}"
  10. # puts "DataSet ids after=#{DataSet.all.map { |ds| ds.id }}"
  11. # # clean up created DataSet
  12. # DataSet.all.each { |ds| ds.delete }
  13. # #FileSet.all.each { |fs| fs.delete }
  14. # end
  15. 1 include Devise::Test::ControllerHelpers
  16. 1 routes { Rails.application.routes }
  17. 1 let(:main_app) { Rails.application.routes.url_helpers }
  18. 1 let(:hyrax) { Hyrax::Engine.routes.url_helpers }
  19. 1 let(:user) { create(:user) }
  20. 1 before do
  21. sign_in user
  22. end
  23. 1 context 'someone elses private work' do # rubocop:disable RSpec/EmptyExampleGroup
  24. # let(:work) { create(:private_data_set) }
  25. #
  26. # it 'shows unauthorized message' do
  27. # get :show, params: { id: work }
  28. # expect(response.code).to eq '401'
  29. # expect(response).to render_template(:unauthorized)
  30. # end
  31. end
  32. end

spec/controllers/hyrax/deepblue_controller_spec.rb

100.0% lines covered

20 relevant lines. 20 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe Hyrax::DeepblueController do
  3. 1 describe "#box_enabled?" do
  4. 1 it "returns false" do
  5. 1 expect(subject.box_enabled?).to eq false
  6. end
  7. end
  8. 1 describe "#display_provenance_log_enabled?" do
  9. 1 it "returns false" do
  10. 1 expect(subject.display_provenance_log_enabled?).to eq false
  11. end
  12. end
  13. 1 describe "#doi_minting_enabled?" do
  14. 1 it "returns false" do
  15. 1 expect(subject.doi_minting_enabled?).to eq false
  16. end
  17. end
  18. 1 describe "#globus_download_enabled?" do
  19. 1 it "returns false" do
  20. 1 expect(subject.globus_download_enabled?).to eq false
  21. end
  22. end
  23. 1 describe "#tombstone_enabled?" do
  24. 1 it "returns false" do
  25. 1 expect(subject.tombstone_enabled?).to eq false
  26. end
  27. end
  28. 1 describe "#zip_download_enabled?" do
  29. 1 it "returns false" do
  30. 1 expect(subject.zip_download_enabled?).to eq false
  31. end
  32. end
  33. end

spec/controllers/hyrax/dissertations_controller_spec.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work Dissertation`
  3. 1 require 'rails_helper'
  4. 1 RSpec.describe Hyrax::DissertationsController do
  5. 1 it "has tests" do
  6. 1 skip "Add your tests here"
  7. end
  8. end

spec/controllers/hyrax/file_sets_controller_spec.rb

100.0% lines covered

56 relevant lines. 56 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe Hyrax::FileSetsController do
  3. 1 describe 'constants' do
  4. 1 it do
  5. 1 expect( Hyrax::FileSetsController::PARAMS_KEY ).to eq 'file_set'
  6. end
  7. end
  8. 1 before {
  9. 9 allow(subject).to receive(:current_user).and_return "user1"
  10. }
  11. 1 describe 'provenance_log_create' do
  12. 1 before {
  13. 1 allow(subject.curation_concern).to receive(:provenance_create).with(current_user: "user1", event_note: 'FileSetsController')
  14. .and_return "provenance log creation"
  15. }
  16. 1 it "calls curation_concern.provenance_create" do
  17. 1 expect(subject.curation_concern).to receive(:provenance_create).with(current_user: "user1", event_note: 'FileSetsController')
  18. 1 expect(subject.provenance_log_create).to eq "provenance log creation"
  19. end
  20. end
  21. 1 describe 'provenance_log_destroy' do
  22. 1 before {
  23. 1 allow(subject.curation_concern).to receive(:provenance_destroy).with(current_user: "user1", event_note: 'FileSetsController')
  24. .and_return "provenance log destruction"
  25. }
  26. 1 it "calls curation_concern.provenance_destroy" do
  27. 1 expect(subject.curation_concern).to receive(:provenance_destroy).with(current_user: "user1", event_note: 'FileSetsController')
  28. 1 expect(subject.provenance_log_destroy).to eq "provenance log destruction"
  29. end
  30. end
  31. 1 describe 'provenance_log_update_after' do
  32. 1 before {
  33. 1 subject.instance_variable_set(:@update_attr_key_values, "after key values")
  34. 1 allow(subject.curation_concern).to receive(:provenance_log_update_after).with(current_user: "user1", update_attr_key_values: "after key values")
  35. .and_return "provenance log update after"
  36. }
  37. 1 it "calls curation_concern.provenance_log_update_after" do
  38. 1 expect(subject.curation_concern).to receive(:provenance_log_update_after).with(current_user: "user1", update_attr_key_values: "after key values")
  39. 1 expect(subject.provenance_log_update_after).to eq "provenance log update after"
  40. end
  41. end
  42. 1 describe 'provenance_log_update_before' do
  43. # NOTE: could not resolve params[PARAMS_KEY].dup
  44. 1 before {
  45. 1 allow(subject.curation_concern).to receive(:provenance_log_update_before).with( anything )
  46. .and_return "provenance log update before"
  47. }
  48. 1 it "sets instance variable to curation_concern.provenance_log_update_before" do
  49. 1 expect(subject.curation_concern).to receive(:provenance_log_update_before)
  50. 1 expect(subject.provenance_log_update_before).to eq "provenance log update before"
  51. 1 subject.instance_variable_get(:@update_attr_key_values) == "provenance log update before"
  52. end
  53. end
  54. 1 describe "display_provenance_log" do
  55. 1 curation = OpenStruct.new(id: 300)
  56. 1 main = "main app"
  57. 1 before {
  58. 1 allow(subject).to receive(:curation_concern).and_return curation
  59. 1 allow(subject).to receive(:main_app).and_return main
  60. 1 allow(Deepblue::ProvenancePath).to receive(:path_for_reference).with( 300 ).and_return "file path"
  61. 1 allow(Deepblue::LoggingHelper).to receive(:bold_debug).with ["DataSetsController", "display_provenance_log", "file path"]
  62. 1 allow(Deepblue::ProvenanceLogService).to receive(:entries).with 300, refresh: true
  63. 1 allow(subject).to receive(:redirect_to).with [main, curation]
  64. }
  65. 1 it "calls Deepblue methods and then redirects" do
  66. 1 expect(subject).to receive(:redirect_to).with [main, curation]
  67. 1 subject.display_provenance_log
  68. end
  69. end
  70. 1 describe "display_provenance_log_enabled?" do
  71. 1 it "returns true" do
  72. 1 expect(subject.display_provenance_log_enabled?).to eq true
  73. end
  74. end
  75. 1 describe "provenance_log_entries_present?" do
  76. 1 context "provenance_log_entries has a value" do
  77. 1 it "returns true" do
  78. 1 skip "Add a test"
  79. end
  80. end
  81. 1 context "provenance_log_entries does not have a value" do
  82. 1 it "returns false" do
  83. 1 skip "Add a test"
  84. end
  85. end
  86. end
  87. end

spec/controllers/hyrax/generic_works_controller_spec.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work GenericWork`
  3. 1 require 'rails_helper'
  4. 1 RSpec.describe Hyrax::GenericWorksController do
  5. 1 it "has tests" do
  6. 1 skip "Add your tests here"
  7. end
  8. end

spec/controllers/hyrax/my/collections_controller_spec.rb

100.0% lines covered

7 relevant lines. 7 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe Hyrax::My::CollectionsController do
  3. 2 let(:subject) { described_class.new }
  4. 1 let(:collection) { FactoryBot.create(:collection_lw) }
  5. 1 describe "#render_bookmarks_control?" do
  6. 1 it "returns false" do
  7. 1 expect(subject.send(:render_bookmarks_control?)).to eq false
  8. end
  9. end
  10. end

spec/controllers/robots_controller_spec.rb

100.0% lines covered

52 relevant lines. 52 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 describe RobotsController do
  3. 3 let(:user) { create(:user) }
  4. 3 let(:admin) { create(:admin) }
  5. 4 let(:robots_txt) { ContentBlock.create(name: 'robots_txt', value: content) }
  6. 4 let(:content) { "User-Agent: *\nDisallow: /concern" }
  7. 1 after do
  8. 9 ContentBlock.delete('robots_txt')
  9. end
  10. 1 describe '#show' do
  11. 1 it 'is blank by default' do
  12. 1 get :show
  13. 1 expect(response).to be_successful
  14. 1 expect(response.body).to eq ''
  15. end
  16. 1 it 'renders the value' do
  17. 1 robots_txt
  18. 1 get :show
  19. 1 expect(response).to be_successful
  20. 1 expect(response.body).to eq content
  21. end
  22. 1 it 'is route for /robots.txt', type: :routing do
  23. 1 expect(get: '/robots.txt').to route_to(controller: 'robots', action: 'show', format: 'txt')
  24. end
  25. end
  26. 1 describe '#edit' do
  27. 1 it 'is unavailable to the public' do
  28. 1 get :edit
  29. 1 expect(response).to redirect_to(new_user_session_path(locale: nil))
  30. end
  31. 1 it 'is unavailable to regular users' do
  32. 1 sign_in user
  33. 1 get :edit
  34. 1 expect(response).to be_unauthorized
  35. end
  36. 1 context 'with rendering' do
  37. 1 render_views
  38. 1 it 'is rendered for admins' do
  39. 1 robots_txt
  40. 1 sign_in admin
  41. 1 get :edit
  42. 1 expect(response).to be_successful
  43. 1 expect(response.body).to include(content)
  44. end
  45. end
  46. end
  47. 1 describe '#update' do
  48. 4 let(:new_content) { 'Disallow: *' }
  49. 1 it 'is unavailable to the public' do
  50. 1 patch :update, params: { content_block: { value: new_content } }
  51. 1 expect(response).to redirect_to(new_user_session_path(locale: nil))
  52. end
  53. 1 it 'is unavailable to regular users' do
  54. 1 sign_in user
  55. 1 patch :update, params: { content_block: { value: new_content } }
  56. 1 expect(response).to be_unauthorized
  57. end
  58. 1 it 'is updated for admins' do
  59. 1 robots_txt
  60. 1 sign_in admin
  61. 1 patch :update, params: { content_block: { value: new_content } }
  62. 1 expect(response).to redirect_to(edit_robots_path)
  63. 1 get :show
  64. 1 expect(response.body).to eq new_content
  65. end
  66. end
  67. end

spec/factories/collection_types.rb

80.33% lines covered

61 relevant lines. 49 lines covered and 12 lines missed.
    
  1. 1 FactoryBot.define do
  2. 1 factory :collection_type, class: Hyrax::CollectionType do
  3. 1 sequence(:title) { |n| "Collection Type #{n}" }
  4. 1 sequence(:machine_id) { |n| "title_#{n}" }
  5. 1 description { 'Collection type with all options' }
  6. 1 nestable { true }
  7. 1 discoverable { true }
  8. 1 sharable { true }
  9. 1 brandable { true }
  10. 1 share_applies_to_new_works { true }
  11. 1 allow_multiple_membership { true }
  12. 1 require_membership { false }
  13. 1 assigns_workflow { false }
  14. 1 assigns_visibility { false }
  15. 1 transient do
  16. 1 creator_user { nil }
  17. 1 creator_group { nil }
  18. 1 manager_user { nil }
  19. 1 manager_group { nil }
  20. end
  21. 1 after(:create) do |collection_type, evaluator|
  22. if evaluator.creator_user
  23. attributes = { hyrax_collection_type_id: collection_type.id,
  24. access: Hyrax::CollectionTypeParticipant::CREATE_ACCESS,
  25. agent_id: evaluator.creator_user,
  26. agent_type: Hyrax::CollectionTypeParticipant::USER_TYPE }
  27. create(:collection_type_participant, attributes)
  28. end
  29. if evaluator.creator_group
  30. attributes = { hyrax_collection_type_id: collection_type.id,
  31. access: Hyrax::CollectionTypeParticipant::CREATE_ACCESS,
  32. agent_id: evaluator.creator_group,
  33. agent_type: Hyrax::CollectionTypeParticipant::GROUP_TYPE }
  34. create(:collection_type_participant, attributes)
  35. end
  36. if evaluator.manager_user
  37. attributes = { hyrax_collection_type_id: collection_type.id,
  38. access: Hyrax::CollectionTypeParticipant::MANAGE_ACCESS,
  39. agent_id: evaluator.manager_user,
  40. agent_type: Hyrax::CollectionTypeParticipant::USER_TYPE }
  41. create(:collection_type_participant, attributes)
  42. end
  43. if evaluator.manager_group
  44. attributes = { hyrax_collection_type_id: collection_type.id,
  45. access: Hyrax::CollectionTypeParticipant::MANAGE_ACCESS,
  46. agent_id: evaluator.manager_group,
  47. agent_type: Hyrax::CollectionTypeParticipant::GROUP_TYPE }
  48. create(:collection_type_participant, attributes)
  49. end
  50. end
  51. 1 trait :nestable do
  52. 1 nestable { true }
  53. end
  54. 1 trait :not_nestable do
  55. 1 nestable { false }
  56. end
  57. 1 trait :discoverable do
  58. 1 discoverable { true }
  59. end
  60. 1 trait :not_discoverable do
  61. 1 discoverable { false }
  62. end
  63. 1 trait :brandable do
  64. 1 brandable { true }
  65. end
  66. 1 trait :not_brandable do
  67. 1 brandable { false }
  68. end
  69. 1 trait :sharable do
  70. 1 sharable { true }
  71. 1 share_applies_to_new_works { true }
  72. end
  73. 1 trait :sharable_no_work_permissions do
  74. 1 sharable { true }
  75. 1 share_applies_to_new_works { false }
  76. end
  77. 1 trait :not_sharable do
  78. 1 sharable { false }
  79. 1 share_applies_to_new_works { false }
  80. end
  81. 1 trait :allow_multiple_membership do
  82. 1 allow_multiple_membership { true }
  83. end
  84. 1 trait :not_allow_multiple_membership do
  85. 1 allow_multiple_membership { false }
  86. end
  87. end
  88. 1 factory :user_collection_type, class: Hyrax::CollectionType do
  89. 8 initialize_with { Hyrax::CollectionType.find_or_create_default_collection_type }
  90. end
  91. 1 factory :admin_set_collection_type, class: Hyrax::CollectionType do
  92. 1 initialize_with { Hyrax::CollectionType.find_or_create_admin_set_type }
  93. end
  94. end

spec/factories/collections.rb

56.6% lines covered

106 relevant lines. 60 lines covered and 46 lines missed.
    
  1. 1 FactoryBot.define do
  2. # Tests that create a Fedora Object are very slow. This factory lets you control which parts of the object ecosystem
  3. # get built.
  4. #
  5. # PREFERRED: Use build whenever possible. You can control the creation of the permission template, collection type, and
  6. # solr document by passing parameters to the build(:collection_lw) method. That way you can build only the parts
  7. # needed for a specific test.
  8. #
  9. # AVOID: Do not use create unless absolutely necessary. It will create everything including the Fedora object.
  10. #
  11. # @example Simple build of a collection with no additional parts created. Lightest weight.
  12. # NOTE: A user is automatically created as the owner of the collection.
  13. # let(:collection) { build(:collection_lw) }
  14. #
  15. # @example Simple build of a collection with no additional parts created. User is the owner of the collection. Lightest weight.
  16. # let(:collection) { build(:collection_lw, user:) }
  17. #
  18. # @example Simple build of a collection with only solr-document. Owner is given edit-access in solr-document. Light weight.
  19. # let(:collection) { build(:collection_lw, with_solr_document: true) }
  20. #
  21. # @example Simple build of a collection with only a permission template created. Owner is set as a manager. Light weight.
  22. # let(:collection) { build(:collection_lw, with_permission_template: true) }
  23. #
  24. # @example Build a collection with only a permission template created. Permissions are set based on
  25. # attributes set for `with_permission_template`. Middle weight.
  26. # # permissions passed thru `with_permission_template` can be any of the following in any combination
  27. # let(:permissions) { { manage_users: [user.user_key], # multiple users can be listed
  28. # deposit_users: [user.user_key],
  29. # view_users: [user.user_key],
  30. # manage_groups: [group_name], # multiple groups can be listed
  31. # deposit_groups: [group_name],
  32. # view_groups: [group_name], } }
  33. # let(:collection) { build(:collection_lw, user: , with_permission_template: permissions) }
  34. #
  35. # @example Build a collection with permission template and solr-document created. Permissions are set based on
  36. # attributes set for `with_permission_template`. Solr-document includes read/edit access defined based
  37. # on attributes passed thru `with_permission_template`. Middle weight.
  38. # # permissions passed thru `with_permission_template` can be any of the following in any combination
  39. # let(:permissions) { { manage_users: [user.user_key], # multiple users can be listed
  40. # deposit_users: [user.user_key],
  41. # view_users: [user.user_key],
  42. # manage_groups: [group_name], # multiple groups can be listed
  43. # deposit_groups: [group_name],
  44. # view_groups: [group_name], } }
  45. # let(:collection) { build(:collection_lw, user: , with_permission_template: permissions, with_solr_document: true) }
  46. #
  47. # @example Build a collection generating its collection type with specific settings. Light Weight.
  48. # NOTE: Do not use this approach if you need access to the collection type in the test.
  49. # DEFAULT: If `collection_type_settings` and `collection_type_gid` are not specified, then the default
  50. # User Collection type will be used.
  51. # # Any not specified default to ON. At least one setting should be specified.
  52. # let(:settings) { [
  53. # :nestable, # OR :not_nestable,
  54. # :discoverable, # OR :not_discoverable
  55. # :brandable, # OR :not_brandable
  56. # :sharable, # OR :not_sharable OR :sharable_no_work_permissions
  57. # :allow_multiple_membership, # OR :not_allow_multiple_membership
  58. # ] }
  59. # let(:collection) { build(:collection_lw, collection_type_settings: settings) }
  60. #
  61. # @example Build a collection using the passed in collection type. Light Weight.
  62. # NOTE: Use this approach if you need access to the collection type in the test.
  63. # # Any not specified default to ON. At least one setting should be specified.
  64. # let(:settings) { [
  65. # :nestable, # OR :not_nestable,
  66. # :discoverable, # OR :not_discoverable
  67. # :brandable, # OR :not_brandable
  68. # :sharable, # OR :not_sharable OR :sharable_no_work_permissions
  69. # :allow_multiple_membership, # OR :not_allow_multiple_membership
  70. # ] }
  71. # let(:collection_type) { create(:collection_lw_type, settings) }
  72. # let(:collection) { build(:collection_lw, collection_type_gid: collection_type.gid) }
  73. #
  74. # @example Build a collection with nesting fields set in the solr document. Light weight.
  75. # NOTE: The property `with_nesting_attributes` is only supported for building collections. The attributes will
  76. # be overwritten by the save process when creating a collection, thus effectively ignoring this property.
  77. # let(:collection) { build(:collection_lw, with_nesting_attributes: { ancestors: ['Parent_1'],
  78. # parent_ids: ['Parent_1'],
  79. # pathnames: ['Parent_1/Collection123'],
  80. # depth: 2 }) }
  81. #
  82. # @example Create a collection with everything. Extreme heavy weight. This is very slow and should be avoided.
  83. # NOTE: Everything gets created.
  84. # NOTE: Build options effect created collections as follows...
  85. # * `with_permission_template` can specify user/group permissions. A permission template is always created.
  86. # * `collection_type_settings` can specify to create a collection type with specific settings
  87. # * `with_solr_document` is ignored. A solr document is always created.
  88. # * `with_nested_attributes` is ignored.
  89. # NOTE: Additional process is required for testing nested collections with Fedora objects. See next example.
  90. # let(:collection) { create(:collection_lw) }
  91. #
  92. # @example Create collections for use with nested collection index testing.
  93. # NOTE: For light weight nested collection testing using solr documents only, see `with_nested_attributes` above
  94. # NOTE: Full indexed nested collections with solr documents and Fedora objects are created by...
  95. # * creating multiple collections (expensive)
  96. # * nesting them and saving - causing reindex of the Fedora objects (expensive)
  97. # For tests of nesting functionality requiring the Fedora object and reindexing, in the test itself
  98. # include `:with_nested_reindexing`
  99. # it "returns the collection and its members", :with_nested_reindexing do
  100. 1 factory :collection_lw, class: Collection do
  101. 1 transient do
  102. 2 user { create(:user) }
  103. 8 collection_type_settings { nil }
  104. 1 with_permission_template { false }
  105. 1 with_nesting_attributes { nil }
  106. 1 with_solr_document { false }
  107. end
  108. 2 sequence(:title) { |n| ["Collection Title #{n}"] }
  109. 1 after(:build) do |collection, evaluator|
  110. 7 collection.apply_depositor_metadata(evaluator.user.user_key)
  111. 7 CollectionLwFactoryHelper.process_collection_type_settings(collection, evaluator)
  112. CollectionLwFactoryHelper.process_with_permission_template(collection, evaluator)
  113. CollectionLwFactoryHelper.process_with_solr_document(collection, evaluator)
  114. CollectionLwFactoryHelper.process_with_nesting_attributes(collection, evaluator)
  115. end
  116. 1 before(:create) do |collection, evaluator|
  117. # force create a permission template if it doesn't exist for the newly created collection
  118. CollectionLwFactoryHelper.process_with_permission_template(collection, evaluator, true) unless evaluator.with_permission_template
  119. end
  120. 1 after(:create) do |collection, _evaluator|
  121. collection.reset_access_controls!
  122. end
  123. 1 factory :public_collection_lw, traits: [:public_lw]
  124. 1 factory :private_collection_lw do
  125. 1 visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE }
  126. end
  127. 1 factory :institution_collection_lw do
  128. 1 visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED }
  129. end
  130. 1 factory :named_collection_lw do
  131. 1 title { ['collection title'] }
  132. 1 description { ['collection description'] }
  133. end
  134. 1 trait :public_lw do
  135. 1 visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC }
  136. end
  137. 1 trait :private_lw do
  138. 1 visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE }
  139. end
  140. 1 trait :institution_lw do
  141. 1 visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED }
  142. end
  143. 1 trait :public_lw do
  144. 1 visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC }
  145. end
  146. end
  147. 1 factory :user_collection_lw, class: Collection do
  148. 1 transient do
  149. 1 user { create(:user) }
  150. end
  151. 1 sequence(:title) { |n| ["User Collection Title #{n}"] }
  152. 1 after(:build) do |collection, evaluator|
  153. collection.apply_depositor_metadata(evaluator.user.user_key)
  154. collection_type = create(:user_collection_type)
  155. collection.collection_type_gid = collection_type.gid
  156. end
  157. end
  158. 1 factory :typeless_collection_lw, class: Collection do
  159. # To create a pre-Hyrax 2.1.0 collection without a collection type gid...
  160. # col = build(:typeless_collection, ...)
  161. # col.save(validate: false)
  162. 1 transient do
  163. 1 user { create(:user) }
  164. 1 with_permission_template { false }
  165. 1 do_save { false }
  166. end
  167. 1 sequence(:title) { |n| ["Typeless Collection Title #{n}"] }
  168. 1 after(:build) do |collection, evaluator|
  169. collection.apply_depositor_metadata(evaluator.user.user_key)
  170. collection.save(validate: false) if evaluator.do_save || evaluator.with_permission_template
  171. if evaluator.with_permission_template
  172. attributes = { source_id: collection.id }
  173. attributes[:manage_users] = [evaluator.user]
  174. attributes = evaluator.with_permission_template.merge(attributes) if evaluator.with_permission_template.respond_to?(:merge)
  175. create(:permission_template, attributes) unless Hyrax::PermissionTemplate.find_by(source_id: collection.id)
  176. end
  177. end
  178. end
  179. 1 class CollectionLwFactoryHelper
  180. # @returns array of user keys
  181. 1 def self.permission_from_template(permission_template_attributes, permission_key)
  182. permissions = []
  183. return permissions if permission_template_attributes.blank?
  184. return permissions unless permission_template_attributes.is_a? Hash
  185. return permissions unless permission_template_attributes.key?(permission_key)
  186. permission_template_attributes[permission_key]
  187. end
  188. 1 private_class_method :permission_from_template
  189. # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role
  190. # @parem [String] creator_user is the user who created the new collection
  191. # @param [Boolean] include_creator, when true, adds the creator_user as a manager
  192. # @returns array of user keys
  193. 1 def self.user_managers(permission_template_attributes, creator_user)
  194. managers = permission_from_template(permission_template_attributes, :manage_users)
  195. managers << creator_user
  196. managers
  197. end
  198. # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role
  199. # @returns array of user keys
  200. 1 def self.group_managers(permission_template_attributes)
  201. permission_from_template(permission_template_attributes, :manage_groups)
  202. end
  203. # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role
  204. # @returns array of user keys
  205. 1 def self.user_depositors(permission_template_attributes)
  206. permission_from_template(permission_template_attributes, :deposit_users)
  207. end
  208. # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role
  209. # @returns array of user keys
  210. 1 def self.group_depositors(permission_template_attributes)
  211. permission_from_template(permission_template_attributes, :deposit_groups)
  212. end
  213. # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role
  214. # @returns array of user keys
  215. 1 def self.user_viewers(permission_template_attributes)
  216. permission_from_template(permission_template_attributes, :view_users)
  217. end
  218. # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role
  219. # @returns array of user keys
  220. 1 def self.group_viewers(permission_template_attributes)
  221. permission_from_template(permission_template_attributes, :view_groups)
  222. end
  223. # Process the collection_type_settings transient property such that...
  224. # * creates the collection type with specified settings if collection_type_settings has settings (ignores collection_type_gid)
  225. # * uses passed in collection type if collection_type_gid is specified AND collection_type_settings is nil
  226. # * uses default User Collection type if neither are specified
  227. # @param [Collection] collection object being built/created by the factory
  228. # @param [Class] evaluator holding the transient properties for the current build/creation process
  229. 1 def self.process_collection_type_settings(collection, evaluator)
  230. 7 if evaluator.collection_type_settings.present?
  231. collection.collection_type = FactoryBot.create(:collection_type, *evaluator.collection_type_settings)
  232. 7 elsif collection.collection_type_gid.blank?
  233. 7 collection.collection_type = FactoryBot.create(:user_collection_type)
  234. end
  235. end
  236. # Process the with_permission_template transient property such that...
  237. # * a permission template is created for the collection
  238. # * a permission template access is created for the collection creator
  239. # * additional permission template accesses are created for each user/group identified in the attributes
  240. # of with_permission_template (created by the permission_template factory)
  241. # @param [Collection] collection object being built/created by the factory
  242. # @param [Class] evaluator holding the transient properties for the current build/creation process
  243. # @param [Boolean] if true, force the permission template to be created
  244. 1 def self.process_with_permission_template(collection, evaluator, force = false)
  245. return unless force || evaluator.with_permission_template || RSpec.current_example.metadata[:with_nested_reindexing]
  246. collection.id ||= FactoryBot.generate(:object_id)
  247. attributes = { source_id: collection.id }
  248. attributes[:manage_users] = user_managers(evaluator.with_permission_template, evaluator.user)
  249. attributes = evaluator.with_permission_template.merge(attributes) if evaluator.with_permission_template.respond_to?(:merge)
  250. FactoryBot.create(:permission_template, attributes) unless Hyrax::PermissionTemplate.find_by(source_id: collection.id)
  251. end
  252. # Process the with_nesting_attributes transient property such that...
  253. # * adds nesting related solr-document fields for ancestors, parent_ids, pathnames, and depth
  254. # @param [Collection] collection object being built/created by the factory
  255. # @param [Class] evaluator holding the transient properties for the current build/creation process
  256. 1 def self.process_with_nesting_attributes(collection, evaluator)
  257. return unless evaluator.with_nesting_attributes.present? && collection.nestable?
  258. Hyrax::Adapters::NestingIndexAdapter.add_nesting_attributes(
  259. solr_doc: solr_document_with_permissions(collection, evaluator),
  260. ancestors: evaluator.with_nesting_attributes[:ancestors],
  261. parent_ids: evaluator.with_nesting_attributes[:parent_ids],
  262. pathnames: evaluator.with_nesting_attributes[:pathnames],
  263. depth: evaluator.with_nesting_attributes[:depth]
  264. )
  265. end
  266. # Process the with_solr_document transient property such that...
  267. # * a solr document is created for the collection
  268. # * permissions identified by with_permission_template, if any, are added to the solr fields
  269. # @param [Collection] collection object being built/created by the factory
  270. # @param [Class] evaluator holding the transient properties for the current build/creation process
  271. 1 def self.process_with_solr_document(collection, evaluator)
  272. return unless evaluator.with_solr_document
  273. return if evaluator.with_nesting_attributes.present? && collection.nestable? # will create the solr document there instead
  274. ActiveFedora::SolrService.add(solr_document_with_permissions(collection, evaluator), commit: true)
  275. end
  276. # Return the collection's solr document with permissions added, such that...
  277. # * permissions identified by with_permission_template, if any, are added to the solr fields
  278. # @param [Collection] collection object being built/created by the factory
  279. # @param [Class] evaluator holding the transient properties for the current build/creation process
  280. # @returns the collection's solr document with permissions added
  281. 1 def self.solr_document_with_permissions(collection, evaluator)
  282. collection.id ||= FactoryBot.generate(:object_id)
  283. collection.edit_users = user_managers(evaluator.with_permission_template, evaluator.user)
  284. collection.edit_groups = group_managers(evaluator.with_permission_template)
  285. collection.read_users = user_viewers(evaluator.with_permission_template) +
  286. user_depositors(evaluator.with_permission_template)
  287. collection.read_groups = group_viewers(evaluator.with_permission_template) +
  288. group_depositors(evaluator.with_permission_template)
  289. collection.to_solr
  290. end
  291. 1 private_class_method :solr_document_with_permissions
  292. end
  293. end

spec/factories/data_sets.rb

65.91% lines covered

88 relevant lines. 58 lines covered and 30 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 FactoryBot.define do
  3. 1 factory :data_set, aliases: [:data_set_work], class: ::DataSet do
  4. 1 transient do
  5. 1 user { create(:user) }
  6. # Set to true (or a hash) if you want to create an admin set
  7. 1 with_admin_set { false }
  8. end
  9. # It is reasonable to assume that a work has an admin set; However, we don't want to
  10. # go through the entire rigors of creating that admin set.
  11. 1 before(:create) do |work, evaluator|
  12. if evaluator.with_admin_set
  13. attributes = {}
  14. attributes[:id] = work.admin_set_id if work.admin_set_id.present?
  15. attributes = evaluator.with_admin_set.merge(attributes) if evaluator.with_admin_set.respond_to?(:merge)
  16. admin_set = create(:admin_set, attributes)
  17. work.admin_set_id = admin_set.id
  18. end
  19. end
  20. 1 after(:create) do |work, _evaluator|
  21. work.save! if work.member_of_collections.present?
  22. end
  23. 1 title { ["Test title"] }
  24. 1 visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE }
  25. 1 authoremail { "test@umich.edu" }
  26. 1 description { ["This is the description."] }
  27. 1 methodology { "The Methodology" }
  28. 1 after(:build) do |work, evaluator|
  29. work.apply_depositor_metadata(evaluator.user.user_key)
  30. end
  31. 1 factory :public_data_set, aliases: [:public_data_set_data_set], traits: [:public]
  32. 1 trait :public do
  33. 1 visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC }
  34. end
  35. 1 factory :private_data_set do
  36. # visibility Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
  37. end
  38. 1 factory :registered_data_set do
  39. 1 read_groups { ["registered"] }
  40. end
  41. 1 factory :data_set_with_one_file do
  42. 1 before(:create) do |work, evaluator|
  43. work.ordered_members << create(:file_set, user: evaluator.user, title: ['A Contained FileSet'], label: 'filename.pdf')
  44. end
  45. end
  46. 1 factory :data_set_with_files do
  47. 1 before(:create) { |work, evaluator| 2.times { work.ordered_members << create(:file_set, user: evaluator.user) } }
  48. end
  49. 1 factory :data_set_with_ordered_files do
  50. 1 before(:create) do |work, evaluator|
  51. work.ordered_members << create(:file_set, user: evaluator.user)
  52. work.ordered_member_proxies.insert_target_at(0, create(:file_set, user: evaluator.user))
  53. end
  54. end
  55. 1 factory :data_set_with_one_child do
  56. 1 before(:create) do |work, evaluator|
  57. work.ordered_members << create(:work, user: evaluator.user, title: ['A Contained Work'])
  58. end
  59. end
  60. 1 factory :data_set_with_two_children do
  61. 1 before(:create) do |work, evaluator|
  62. work.ordered_members << create(:work, user: evaluator.user, title: ['A Contained Work'], id: "BlahBlah1")
  63. work.ordered_members << create(:work, user: evaluator.user, title: ['Another Contained Work'], id: "BlahBlah2")
  64. end
  65. end
  66. 1 factory :data_set_with_representative_file do
  67. 1 before(:create) do |work, evaluator|
  68. work.ordered_members << create(:file_set, user: evaluator.user, title: ['A Contained FileSet'])
  69. work.representative_id = work.members[0].id
  70. end
  71. end
  72. 1 factory :data_set_with_file_and_data_set do
  73. 1 before(:create) do |work, evaluator|
  74. work.ordered_members << create(:file_set, user: evaluator.user)
  75. work.ordered_members << create(:work, user: evaluator.user)
  76. end
  77. end
  78. 1 factory :with_embargo_date do
  79. # build with defaults:
  80. # let(:work) { create(:embargoed_data_set) }
  81. # build with specific values:
  82. # let(:embargo_attributes) do
  83. # { embargo_date: Date.tomorrow.to_s,
  84. # current_state: Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE,
  85. # future_state: Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC }
  86. # end
  87. # let(:work) { create(:embargoed_data_set, with_embargo_attributes: embargo_attributes) }
  88. 1 transient do
  89. 1 with_embargo_attributes { false }
  90. 1 embargo_date { Date.tomorrow.to_s }
  91. 1 current_state { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE }
  92. 1 future_state { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC }
  93. end
  94. 1 factory :embargoed_data_set do
  95. 1 after(:build) do |work, evaluator|
  96. if evaluator.with_embargo_attributes
  97. work.apply_embargo(evaluator.with_embargo_attributes[:embargo_date],
  98. evaluator.with_embargo_attributes[:current_state],
  99. evaluator.with_embargo_attributes[:future_state])
  100. else
  101. work.apply_embargo(evaluator.embargo_date,
  102. evaluator.current_state,
  103. evaluator.future_state)
  104. end
  105. end
  106. end
  107. 1 factory :embargoed_data_set_with_files do
  108. 1 after(:build) do |work, evaluator|
  109. if evaluator.with_embargo_attributes
  110. work.apply_embargo(evaluator.with_embargo_attributes[:embargo_date],
  111. evaluator.with_embargo_attributes[:current_state],
  112. evaluator.with_embargo_attributes[:future_state])
  113. else
  114. work.apply_embargo(evaluator.embargo_date,
  115. evaluator.current_state,
  116. evaluator.future_state)
  117. end
  118. end
  119. 1 after(:create) { |work, evaluator| 2.times { work.ordered_members << create(:file_set, user: evaluator.user) } }
  120. end
  121. end
  122. 1 factory :with_lease_date do
  123. # build with defaults:
  124. # let(:work) { create(:leased_data_set) }
  125. # build with specific values:
  126. # let(:lease_attributes) do
  127. # { lease_date: Date.tomorrow.to_s,
  128. # current_state: Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC,
  129. # future_state: Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED }
  130. # end
  131. # let(:work) { create(:leased_data_set, with_lease_attributes: lease_attributes) }
  132. 1 transient do
  133. 1 with_lease_attributes { false }
  134. 1 lease_date { Date.tomorrow.to_s }
  135. 1 current_state { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC }
  136. 1 future_state { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE }
  137. end
  138. 1 factory :leased_data_set do
  139. 1 after(:build) do |work, evaluator|
  140. if evaluator.with_lease_attributes
  141. work.apply_lease(evaluator.with_lease_attributes[:lease_date],
  142. evaluator.with_lease_attributes[:current_state],
  143. evaluator.with_lease_attributes[:future_state])
  144. else
  145. work.apply_lease(evaluator.lease_date,
  146. evaluator.current_state,
  147. evaluator.future_state)
  148. end
  149. end
  150. end
  151. 1 factory :leased_data_set_with_files do
  152. 1 after(:build) do |work, evaluator|
  153. if evaluator.with_lease_attributes
  154. work.apply_lease(evaluator.with_lease_attributes[:lease_date],
  155. evaluator.with_lease_attributes[:current_state],
  156. evaluator.with_lease_attributes[:future_state])
  157. else
  158. work.apply_lease(evaluator.lease_date,
  159. evaluator.current_state,
  160. evaluator.future_state)
  161. end
  162. end
  163. 1 after(:create) { |work, evaluator| 2.times { work.ordered_members << create(:file_set, user: evaluator.user) } }
  164. end
  165. end
  166. end
  167. # Doesn't set up any edit_users
  168. 1 factory :data_set_without_access, class: DataSet do
  169. 1 title { ['Test title'] }
  170. 1 depositor { create(:user).user_key }
  171. end
  172. end

spec/factories/file_sets.rb

73.68% lines covered

19 relevant lines. 14 lines covered and 5 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 FactoryBot.define do
  3. 1 factory :file_set do
  4. 1 transient do
  5. 1 user { create(:user) }
  6. 1 content { nil }
  7. end
  8. 1 after(:build) do |fs, evaluator|
  9. fs.apply_depositor_metadata evaluator.user.user_key
  10. end
  11. 1 after(:create) do |file, evaluator|
  12. Hydra::Works::UploadFileToFileSet.call(file, evaluator.content) if evaluator.content
  13. end
  14. 1 trait :public do
  15. 1 read_groups { ["public"] }
  16. end
  17. 1 trait :registered do
  18. 1 read_groups { ["registered"] }
  19. end
  20. 1 factory :file_with_work do
  21. 1 after(:build) do |file, _evaluator|
  22. file.title = ['testfile']
  23. end
  24. 1 after(:create) do |file, evaluator|
  25. Hydra::Works::UploadFileToFileSet.call(file, evaluator.content) if evaluator.content
  26. create(:work, user: evaluator.user).members << file
  27. end
  28. end
  29. end
  30. end

spec/factories/object_id.rb

66.67% lines covered

3 relevant lines. 2 lines covered and 1 lines missed.
    
  1. # frozen_string_literal: true
  2. # Defines a new sequence
  3. 1 FactoryBot.define do
  4. 1 sequence :object_id do |n|
  5. "object_id_#{n}"
  6. end
  7. end

spec/factories/permission_template_accesses.rb

100.0% lines covered

9 relevant lines. 9 lines covered and 0 lines missed.
    
  1. 1 FactoryBot.define do
  2. 1 factory :permission_template_access, class: Hyrax::PermissionTemplateAccess do
  3. 1 permission_template
  4. 1 trait :manage do
  5. 1 access { 'manage' }
  6. end
  7. 1 trait :deposit do
  8. 1 access { 'deposit' }
  9. end
  10. 1 trait :view do
  11. 1 access { 'view' }
  12. end
  13. end
  14. end

spec/factories/permission_templates.rb

39.13% lines covered

46 relevant lines. 18 lines covered and 28 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 FactoryBot.define do
  3. 1 factory :permission_template, class: Hyrax::PermissionTemplate do
  4. # Given that there is a one to one strong relation between permission_template and admin_set,
  5. # with a unique index on the source_id, I don't want to have duplication in source_id
  6. 1 sequence(:source_id) { |n| format("%010d", n) }
  7. 1 before(:create) do |permission_template, evaluator|
  8. if evaluator.with_admin_set
  9. source_id = permission_template.source_id
  10. admin_set =
  11. if source_id.present?
  12. begin
  13. AdminSet.find(source_id)
  14. rescue ActiveFedora::ObjectNotFoundError
  15. create(:admin_set, id: source_id)
  16. end
  17. else
  18. create(:admin_set)
  19. end
  20. permission_template.source_id = admin_set.id
  21. elsif evaluator.with_collection
  22. source_id = permission_template.source_id
  23. collection =
  24. if source_id.present?
  25. begin
  26. Collection.find(source_id)
  27. rescue ActiveFedora::ObjectNotFoundError
  28. create(:collection, id: source_id)
  29. end
  30. else
  31. create(:collection)
  32. end
  33. permission_template.source_id = collection.id
  34. end
  35. end
  36. 1 after(:create) do |permission_template, evaluator|
  37. if evaluator.with_workflows
  38. Hyrax::Workflow::WorkflowImporter.load_workflow_for(permission_template: permission_template)
  39. Sipity::Workflow.activate!(permission_template: permission_template, workflow_id: permission_template.available_workflows.pluck(:id).first)
  40. end
  41. if evaluator.with_active_workflow
  42. workflow = create(:workflow, active: true, permission_template: permission_template)
  43. create(:workflow_action, workflow: workflow) # Need to create a single action that can be taken
  44. end
  45. AccessHelper.create_access(permission_template, 'user', :manage, evaluator.manage_users) if evaluator.manage_users.present?
  46. AccessHelper.create_access(permission_template, 'group', :manage, evaluator.manage_groups) if evaluator.manage_groups.present?
  47. AccessHelper.create_access(permission_template, 'user', :deposit, evaluator.deposit_users) if evaluator.deposit_users.present?
  48. AccessHelper.create_access(permission_template, 'group', :deposit, evaluator.deposit_groups) if evaluator.deposit_groups.present?
  49. AccessHelper.create_access(permission_template, 'user', :view, evaluator.view_users) if evaluator.view_users.present?
  50. AccessHelper.create_access(permission_template, 'group', :view, evaluator.view_groups) if evaluator.view_groups.present?
  51. end
  52. 1 transient do
  53. 1 with_admin_set { false }
  54. 1 with_collection { false }
  55. 1 with_workflows { false }
  56. 1 with_active_workflow { false }
  57. 1 manage_users { nil }
  58. 1 manage_groups { nil }
  59. 1 deposit_users { nil }
  60. 1 deposit_groups { nil }
  61. 1 view_users { nil }
  62. 1 view_groups { nil }
  63. end
  64. end
  65. 1 class AccessHelper
  66. 1 def self.create_access(permission_template_id, agent_type, access, agent_ids)
  67. agent_ids.each do |agent_id|
  68. FactoryBot.create(:permission_template_access,
  69. access,
  70. permission_template: permission_template_id,
  71. agent_type: agent_type,
  72. agent_id: agent_id)
  73. end
  74. end
  75. end
  76. end

spec/factories/users.rb

63.33% lines covered

30 relevant lines. 19 lines covered and 11 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 FactoryBot.define do
  3. 1 factory :user do
  4. 34 sequence(:email) { |n| "user#{n}@example.com" }
  5. 34 encrypted_password { 'password' }
  6. 1 transient do
  7. # Allow for custom groups when a user is instantiated.
  8. # @example create(:user, groups: 'avacado')
  9. 34 groups { [] }
  10. end
  11. # TODO: Register the groups for the given user key such that we can remove the following from other specs:
  12. # `allow(::User.group_service).to receive(:byname).and_return(user.user_key => ['admin'])``
  13. 1 after(:build) do |user, evaluator|
  14. # In case we have the instance but it has not been persisted
  15. 33 ::RSpec::Mocks.allow_message(user, :groups).and_return(Array.wrap(evaluator.groups))
  16. # Given that we are stubbing the class, we need to allow for the original to be called
  17. 33 ::RSpec::Mocks.allow_message(user.class.group_service, :fetch_groups).and_call_original
  18. # We need to ensure that each instantiation of the admin user behaves as expected.
  19. # This resolves the issue of both the created object being used as well as re-finding the created object.
  20. 33 ::RSpec::Mocks.allow_message(user.class.group_service, :fetch_groups).with(user: user).and_return(Array.wrap(evaluator.groups))
  21. end
  22. 1 factory :admin do
  23. 6 roles { [Role.where(name: 'admin').first_or_create] }
  24. end
  25. 1 factory :user_with_mail do
  26. 1 after(:create) do |user|
  27. # Create examples of single file successes and failures
  28. (1..10).each do |number|
  29. file = MockFile.new(number.to_s, "Single File #{number}")
  30. User.batch_user.send_message(user, 'File 1 could not be updated. You do not have sufficient privileges to edit it.', file.to_s, false)
  31. User.batch_user.send_message(user, 'File 1 has been saved', file.to_s, false)
  32. end
  33. # Create examples of mulitple file successes and failures
  34. files = []
  35. (1..50).each do |number|
  36. files << MockFile.new(number.to_s, "File #{number}")
  37. end
  38. User.batch_user.send_message(user, 'These files could not be updated. You do not have sufficient privileges to edit them.', 'Batch upload permission denied', false)
  39. User.batch_user.send_message(user, 'These files have been saved', 'Batch upload complete', false)
  40. end
  41. end
  42. end
  43. 1 trait :guest do
  44. 1 guest { true }
  45. end
  46. end
  47. 1 class MockFile
  48. 1 attr_accessor :to_s, :id
  49. 1 def initialize(id, string)
  50. self.id = id
  51. self.to_s = string
  52. end
  53. end

spec/factories/workflows.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. 1 FactoryBot.define do
  2. 1 factory :workflow, class: Sipity::Workflow do
  3. 1 sequence(:name) { |n| "generic_work-#{n}" }
  4. 1 permission_template
  5. end
  6. end

spec/features/create_data_set_spec.rb

75.0% lines covered

16 relevant lines. 12 lines covered and 4 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 include Warden::Test::Helpers
  3. # NOTE: If you generated more than one work, you have to set "js: true"
  4. 1 RSpec.feature 'Create a DataSet', js: true do
  5. # before(:all ) do
  6. # puts "DataSet ids before=#{DataSet.all.map { |ds| ds.id }}"
  7. # #puts "FileSet ids before=#{FileSet.all.map { |fs| fs.id }}"
  8. # end
  9. #
  10. # after(:all ) do
  11. # #puts "FileSet ids after=#{FileSet.all.map { |fs| fs.id }}"
  12. # puts "DataSet ids after=#{DataSet.all.map { |ds| ds.id }}"
  13. # # clean up created DataSet
  14. # DataSet.all.each { |ds| ds.delete }
  15. # #FileSet.all.each { |fs| fs.delete }
  16. # end
  17. 1 context 'a logged in user' do
  18. 1 let(:user_attributes) do
  19. { email: 'test@example.com' }
  20. end
  21. 1 let(:user) do
  22. User.new(user_attributes) { |u| u.save(validate: false) }
  23. end
  24. 2 let(:admin_set_id) { AdminSet.find_or_create_default_admin_set_id }
  25. 2 let(:permission_template) { Hyrax::PermissionTemplate.find_or_create_by!(source_id: admin_set_id) }
  26. 2 let(:workflow) { Sipity::Workflow.create!(active: true, name: 'test-workflow', permission_template: permission_template) }
  27. 1 before do
  28. # Create a single action that can be taken
  29. 1 Sipity::WorkflowAction.create!(name: 'submit', workflow: workflow)
  30. # Grant the user access to deposit into the admin set.
  31. Hyrax::PermissionTemplateAccess.create!(
  32. permission_template_id: permission_template.id,
  33. agent_type: 'user',
  34. agent_id: user.user_key,
  35. access: 'deposit'
  36. )
  37. login_as user
  38. end
  39. 1 scenario do
  40. # visit '/dashboard'
  41. # click_link "Works"
  42. # expect(page).to have_content "Add new work"
  43. # click_link "Add new work"
  44. #
  45. # # If you generate more than one work uncomment these lines
  46. # choose "payload_concern", option: "DataSet"
  47. # click_button "Create work"
  48. # sleep 2 # seems to make this work
  49. # expect(page).to have_content "Add New Data Set"
  50. # click_link "Files" # switch tab
  51. # expect(page).to have_content "Add files"
  52. # expect(page).to have_content "Add folder"
  53. # within('span#addfiles') do
  54. # attach_file("files[]", "#{Hyrax::Engine.root}/spec/fixtures/image.jp2", visible: false)
  55. # attach_file("files[]", "#{Hyrax::Engine.root}/spec/fixtures/jp2_fits.xml", visible: false)
  56. # end
  57. # click_link "Descriptions" # switch tab
  58. # fill_in('Title', with: 'My Test Work')
  59. # fill_in('Creator', with: 'Doe, Jane')
  60. # fill_in('Authoremail', with: 'test@test.com' )
  61. # fill_in('Keyword', with: 'testing')
  62. # fill_in('Abstract or Summary', with: 'This is the description.' )
  63. # select('In Copyright', from: 'Rights statement')
  64. #
  65. # # With selenium and the chrome driver, focus remains on the
  66. # # select box. Click outside the box so the next line can't find
  67. # # its element
  68. # find('body').click
  69. # choose('data_set_visibility_open')
  70. # expect(page).to have_content('Please note, making something visible to the world (i.e. marking this as Public) may be viewed as publishing which could impact your ability to')
  71. #
  72. # # the upload of files fails with:
  73. # # 2018-05-04 12:02:27 -0400: Rack app error handling request { POST /uploads/ }
  74. # # #<ActiveRecord::StatementInvalid: SQLite3::BusyException: database is locked: INSERT INTO "uploaded_files" ("file", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)>
  75. # # check('agreement')
  76. # # click_on('Save')
  77. # # expect(page).to have_content('My Test Work')
  78. # # expect(page).to have_content "Your files are being processed by Hyrax in the background."
  79. end
  80. end
  81. end

spec/features/create_dissertation_spec.rb

75.0% lines covered

16 relevant lines. 12 lines covered and 4 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work Dissertation`
  3. 1 require 'rails_helper'
  4. 1 include Warden::Test::Helpers
  5. # NOTE: If you generated more than one work, you have to set "js: true"
  6. 1 RSpec.feature 'Create a Dissertation', js: true do
  7. 1 context 'a logged in user' do
  8. 1 let(:user_attributes) do
  9. { email: 'test@example.com' }
  10. end
  11. 1 let(:user) do
  12. User.new(user_attributes) { |u| u.save(validate: false) }
  13. end
  14. 2 let(:admin_set_id) { AdminSet.find_or_create_default_admin_set_id }
  15. 2 let(:permission_template) { Hyrax::PermissionTemplate.find_or_create_by!(source_id: admin_set_id) }
  16. 2 let(:workflow) { Sipity::Workflow.create!(active: true, name: 'test-workflow', permission_template: permission_template) }
  17. 1 before do
  18. # Create a single action that can be taken
  19. 1 Sipity::WorkflowAction.create!(name: 'submit', workflow: workflow)
  20. # Grant the user access to deposit into the admin set.
  21. Hyrax::PermissionTemplateAccess.create!(
  22. permission_template_id: permission_template.id,
  23. agent_type: 'user',
  24. agent_id: user.user_key,
  25. access: 'deposit'
  26. )
  27. login_as user
  28. end
  29. 1 scenario do
  30. # visit '/dashboard'
  31. # click_link "Works"
  32. # click_link "Add new work"
  33. #
  34. # # If you generate more than one work uncomment these lines
  35. # choose "payload_concern", option: "Dissertation"
  36. # click_button "Create work"
  37. # sleep 2 # seems to make this work
  38. # expect(page).to have_content "Add New Dissertation"
  39. # click_link "Files" # switch tab
  40. # expect(page).to have_content "Add files"
  41. # expect(page).to have_content "Add folder"
  42. # within('span#addfiles') do
  43. # attach_file("files[]", "#{Hyrax::Engine.root}/spec/fixtures/image.jp2", visible: false)
  44. # attach_file("files[]", "#{Hyrax::Engine.root}/spec/fixtures/jp2_fits.xml", visible: false)
  45. # end
  46. # click_link "Descriptions" # switch tab
  47. # fill_in('Title', with: 'My Test Work')
  48. # fill_in('Creator', with: 'Doe, Jane')
  49. # #fill_in('Keyword', with: 'testing')
  50. # select('In Copyright', from: 'Rights statement')
  51. #
  52. # # With selenium and the chrome driver, focus remains on the
  53. # # select box. Click outside the box so the next line can't find
  54. # # its element
  55. # find('body').click
  56. # choose('dissertation_visibility_open')
  57. # expect(page).to have_content('Please note, making something visible to the world (i.e. marking this as Public) may be viewed as publishing which could impact your ability to')
  58. #
  59. # # the upload of files fails with:
  60. # # 2018-05-04 12:04:05 -0400: Rack app error handling request { POST /uploads/ }
  61. # # #<ActiveRecord::StatementInvalid: SQLite3::BusyException: database is locked: INSERT INTO "uploaded_files" ("file", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)>
  62. # # check('agreement')
  63. # # click_on('Save')
  64. # # expect(page).to have_content('My Test Work')
  65. # # expect(page).to have_content "Your files are being processed by Hyrax in the background."
  66. end
  67. end
  68. end

spec/features/create_generic_work_spec.rb

75.0% lines covered

16 relevant lines. 12 lines covered and 4 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work GenericWork`
  3. 1 require 'rails_helper'
  4. 1 include Warden::Test::Helpers
  5. # NOTE: If you generated more than one work, you have to set "js: true"
  6. 1 RSpec.feature 'Create a GenericWork', js: false do
  7. 1 context 'a logged in user' do
  8. 1 let(:user_attributes) do
  9. { email: 'test@example.com' }
  10. end
  11. 1 let(:user) do
  12. User.new(user_attributes) { |u| u.save(validate: false) }
  13. end
  14. 2 let(:admin_set_id) { AdminSet.find_or_create_default_admin_set_id }
  15. 2 let(:permission_template) { Hyrax::PermissionTemplate.find_or_create_by!(source_id: admin_set_id) }
  16. 2 let(:workflow) { Sipity::Workflow.create!(active: true, name: 'test-workflow', permission_template: permission_template) }
  17. 1 before do
  18. # Create a single action that can be taken
  19. 1 Sipity::WorkflowAction.create!(name: 'submit', workflow: workflow)
  20. # Grant the user access to deposit into the admin set.
  21. Hyrax::PermissionTemplateAccess.create!(
  22. permission_template_id: permission_template.id,
  23. agent_type: 'user',
  24. agent_id: user.user_key,
  25. access: 'deposit'
  26. )
  27. login_as user
  28. end
  29. 1 scenario do
  30. # # comment out until we can figure out why this error is happening
  31. # # ActiveRecord::StatementInvalid:
  32. # # SQLite3::BusyException: database is locked: UPDATE "users" SET "sign_in_count" = ?, "current_sign_in_at" = ?, "last_sign_in_at" = ?, "current_sign_in_ip" = ?, "last_sign_in_ip" = ?, "updated_at" = ? WHERE "users"."id" = ?
  33. # visit '/dashboard'
  34. # click_link "Works"
  35. # click_link "Add new work"
  36. #
  37. # # If you generate more than one work uncomment these lines
  38. # # choose "payload_concern", option: "GenericWork"
  39. # # click_button "Create work"
  40. #
  41. # expect(page).to have_content "Add New Generic work"
  42. # click_link "Files" # switch tab
  43. # expect(page).to have_content "Add files"
  44. # expect(page).to have_content "Add folder"
  45. # within('span#addfiles') do
  46. # attach_file("files[]", "#{Hyrax::Engine.root}/spec/fixtures/image.jp2", visible: false)
  47. # attach_file("files[]", "#{Hyrax::Engine.root}/spec/fixtures/jp2_fits.xml", visible: false)
  48. # end
  49. # click_link "Descriptions" # switch tab
  50. # fill_in('Title', with: 'My Test Work')
  51. # fill_in('Creator', with: 'Doe, Jane')
  52. # fill_in('Keyword', with: 'testing')
  53. # select('In Copyright', from: 'Rights statement')
  54. #
  55. # # With selenium and the chrome driver, focus remains on the
  56. # # select box. Click outside the box so the next line can't find
  57. # # its element
  58. # find('body').click
  59. # choose('generic_work_visibility_open')
  60. # expect(page).to have_content('Please note, making something visible to the world (i.e. marking this as Public) may be viewed as publishing which could impact your ability to')
  61. # check('agreement')
  62. #
  63. # click_on('Save')
  64. # expect(page).to have_content('My Test Work')
  65. # expect(page).to have_content "Your files are being processed by Hyrax in the background."
  66. end
  67. end
  68. end

spec/forms/hyrax/collection_form_spec.rb

100.0% lines covered

5 relevant lines. 5 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'rails_helper'
  3. 1 describe Hyrax::Forms::CollectionForm do
  4. 1 describe "#terms" do
  5. 2 subject { described_class.terms }
  6. 2 it { is_expected.to eq %i[
  7. authoremail
  8. based_near
  9. collection_type_gid
  10. contributor
  11. creator
  12. date_coverage
  13. date_created
  14. description
  15. fundedby
  16. grantnumber
  17. identifier
  18. keyword
  19. language
  20. license
  21. methodology
  22. publisher
  23. referenced_by
  24. related_url
  25. representative_id
  26. resource_type
  27. rights_license
  28. subject
  29. subject_discipline
  30. thumbnail_id
  31. title
  32. visibility
  33. ] }
  34. end
  35. end

spec/forms/hyrax/data_set_form_spec.rb

100.0% lines covered

59 relevant lines. 59 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'rails_helper'
  3. 1 RSpec.describe Hyrax::DataSetForm do
  4. # before(:all ) do
  5. # puts "DataSet ids before=#{DataSet.all.map { |ds| ds.id }}"
  6. # puts "FileSet ids before=#{FileSet.all.map { |fs| fs.id }}"
  7. # end
  8. #
  9. # after(:all ) do
  10. # puts "FileSet ids after=#{FileSet.all.map { |fs| fs.id }}"
  11. # puts "DataSet ids after=#{DataSet.all.map { |ds| ds.id }}"
  12. # # clean up created DataSet
  13. # DataSet.all.each { |ds| ds.delete }
  14. # FileSet.all.each { |fs| fs.delete }
  15. # end
  16. 6 subject { form }
  17. 15 let(:work) { DataSet.new }
  18. 15 let(:user) { create(:user) }
  19. 15 let(:ability) { Ability.new(user) }
  20. 15 let(:form) { described_class.new(work, ability, nil) }
  21. 3 let( :expected_required_fields ) { %i[
  22. title
  23. creator
  24. authoremail
  25. methodology
  26. description
  27. rights_license
  28. resource_type
  29. description_abstract
  30. publisher
  31. ] }
  32. 3 let( :expected_primary_terms ) { %i[
  33. title
  34. creator
  35. authoremail
  36. methodology
  37. resource_type
  38. description_abstract
  39. description
  40. publisher
  41. date_coverage
  42. rights_license
  43. rights_license_other
  44. license_other
  45. fundedby
  46. fundedby_other
  47. keyword
  48. language
  49. referenced_by
  50. geo_location_place
  51. geo_location_box
  52. ] }
  53. 1 describe '#data_set?' do
  54. 1 it 'returns true' do
  55. 1 expect(form.data_set?).to eq true
  56. end
  57. end
  58. 1 describe "#required_fields" do
  59. 2 subject { form.required_fields }
  60. 2 it { is_expected.to eq expected_required_fields }
  61. end
  62. 1 describe "#primary_terms" do
  63. 2 subject { form.primary_terms }
  64. 1 it do
  65. 1 is_expected.to eq expected_primary_terms
  66. end
  67. end
  68. 1 describe "#secondary_terms" do
  69. 2 subject { form.secondary_terms }
  70. 1 it do
  71. 1 is_expected.not_to include( :title,
  72. :creator,
  73. :keyword,
  74. :visibilty,
  75. :visibility_during_embargo,
  76. :embargo_release_date,
  77. :visibility_after_embargo,
  78. :visibility_during_lease,
  79. :lease_expiration_date,
  80. :visibility_arights_statementfter_lease,
  81. :collection_ids,
  82. :additional_information )
  83. 1 is_expected.not_to include( *expected_required_fields )
  84. 1 is_expected.not_to include( *expected_primary_terms )
  85. # is_expected.to include( :additional_information )
  86. end
  87. end
  88. 1 describe "#[]" do
  89. 3 subject { form[term] }
  90. 1 context "for member_of_collection_ids" do
  91. 3 let(:term) { :member_of_collection_ids }
  92. 2 it { is_expected.to be_empty }
  93. 1 context "when the model has collection ids" do
  94. 1 before do
  95. 1 allow(work).to receive(:member_of_collection_ids).and_return(['col1', 'col2'])
  96. end
  97. # This allows the edit form to show collections the work is already a member of.
  98. 2 it { is_expected.to eq ['col1', 'col2'] }
  99. end
  100. end
  101. end
  102. 1 describe '.model_attributes' do # rubocop:disable RSpec/EmptyExampleGroup
  103. # let(:permission_template) { create(:permission_template, source_id: source_id) }
  104. # let!(:workflow) { create(:workflow, active: true, permission_template_id: permission_template.id) }
  105. # let(:source_id) { '123' }
  106. # let(:file_set) { create(:file_set) }
  107. # let(:params) do
  108. # ActionController::Parameters.new(
  109. # title: ['foo'],
  110. # description: [''],
  111. # visibility: 'open',
  112. # source_id: source_id,
  113. # representative_id: '456',
  114. # rendering_ids: [file_set.id],
  115. # thumbnail_id: '789',
  116. # keyword: ['derp'],
  117. # license: ['http://creativecommons.org/licenses/by/3.0/us/'],
  118. # member_of_collection_ids: ['123456', 'abcdef']
  119. # )
  120. # end
  121. #
  122. # subject { described_class.model_attributes(params) }
  123. #
  124. # it 'permits parameters' do
  125. # expect(subject['title']).to eq ['foo']
  126. # expect(subject['description']).to be_empty
  127. # expect(subject['visibility']).to eq 'open'
  128. # expect(subject['license']).to eq ['http://creativecommons.org/licenses/by/3.0/us/']
  129. # expect(subject['keyword']).to eq ['derp']
  130. # expect(subject['member_of_collection_ids']).to eq ['123456', 'abcdef']
  131. # expect(subject['rendering_ids']).to eq [file_set.id]
  132. # end
  133. #
  134. # context '.model_attributes' do
  135. # let(:params) do
  136. # ActionController::Parameters.new(
  137. # title: [''],
  138. # description: [''],
  139. # keyword: [''],
  140. # license: [''],
  141. # member_of_collection_ids: [''],
  142. # on_behalf_of: 'Melissa'
  143. # )
  144. # end
  145. #
  146. # it 'removes blank parameters' do
  147. # expect(subject['title']).to be_empty
  148. # expect(subject['description']).to be_empty
  149. # expect(subject['license']).to be_empty
  150. # expect(subject['keyword']).to be_empty
  151. # expect(subject['member_of_collection_ids']).to be_empty
  152. # expect(subject['on_behalf_of']).to eq 'Melissa'
  153. # end
  154. # end
  155. end
  156. 1 describe "#visibility" do
  157. 2 subject { form.visibility }
  158. 2 it { is_expected.to eq 'open' }
  159. end
  160. 2 it { is_expected.to delegate_method(:on_behalf_of).to(:model) }
  161. 2 it { is_expected.to delegate_method(:depositor).to(:model) }
  162. 2 it { is_expected.to delegate_method(:permissions).to(:model) }
  163. 1 describe "#agreement_accepted" do
  164. 2 subject { form.agreement_accepted }
  165. 2 it { is_expected.to eq false }
  166. end
  167. 1 context "on a work already saved" do
  168. 2 before { allow(work).to receive(:new_record?).and_return(false) }
  169. 1 it "defaults deposit agreement to true" do
  170. 1 expect(form.agreement_accepted).to eq(true)
  171. end
  172. end
  173. 1 describe "#merge_date_coverage_attributes!" do
  174. 1 before {
  175. 2 subject.instance_variable_set(:@attributes, { "three" => "3", "four" => "4" })
  176. }
  177. 1 context "when called with hash argument" do
  178. 1 it "merges with @attributes" do
  179. 1 subject.merge_date_coverage_attributes! Hash.new( :one => "1", :two => "2" )
  180. 1 subject.instance_variable_get(:@attributes) == Hash.new( "one" => "1", "two" => "2", "three" => "3", "four" => "4" )
  181. end
  182. end
  183. 1 context "when called with empty hash" do
  184. 1 it "keeps the same @attributes" do
  185. 1 subject.merge_date_coverage_attributes! Hash.new{ }
  186. 1 subject.instance_variable_get(:@attributes) == Hash.new( "three" => "3", "four" => "4" )
  187. end
  188. end
  189. end
  190. end

spec/forms/hyrax/dissertation_form_spec.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work Dissertation`
  3. 1 require 'rails_helper'
  4. 1 RSpec.describe Hyrax::DissertationForm do
  5. 1 it "has tests" do
  6. 1 skip "Add your tests here"
  7. end
  8. end

spec/forms/hyrax/generic_work_form_spec.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work GenericWork`
  3. 1 require 'rails_helper'
  4. 1 RSpec.describe Hyrax::GenericWorkForm do
  5. 1 it "has tests" do
  6. 1 skip "Add your tests here"
  7. end
  8. end

spec/helpers/deepblue/event_helper_spec.rb

100.0% lines covered

69 relevant lines. 69 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class CurationConcernMock
  3. end
  4. 1 class CurationConcernWithProvLoggingMock
  5. 1 include ::Deepblue::ProvenanceBehavior
  6. end
  7. 1 RSpec.describe Deepblue::EventHelper, type: :helper do
  8. 7 let( :user ) { 'user@umich.edu' }
  9. 1 describe '.after_batch_create_failure_callback' do
  10. 2 let( :event_name ) { 'after_batch_create_failure' }
  11. 2 let( :arrow_line ) { ">>>>> #{event_name} >>>>>" }
  12. 1 before do
  13. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  14. end
  15. 1 it do
  16. 1 Deepblue::EventHelper.after_batch_create_failure_callback( user: user )
  17. 1 expect( Rails.logger ).to have_received( :debug ).with( arrow_line ).exactly( 4 ).times
  18. 1 expect( Rails.logger ).to have_received( :debug ).with( "#{event_name} >>>>> #{user}" )
  19. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 5 ).times
  20. end
  21. end
  22. 1 describe '.after_batch_create_success_callback' do
  23. 2 let( :event_name ) { 'after_batch_create_success' }
  24. 2 let( :arrow_line ) { ">>>>> #{event_name} >>>>>" }
  25. 1 before do
  26. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  27. end
  28. 1 it do
  29. 1 Deepblue::EventHelper.after_batch_create_success_callback( user: user )
  30. 1 expect( Rails.logger ).to have_received( :debug ).with( arrow_line ).exactly( 4 ).times
  31. 1 expect( Rails.logger ).to have_received( :debug ).with( "#{event_name} >>>>> #{user}" )
  32. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 5 ).times
  33. end
  34. end
  35. 1 describe '.after_create_concern_callback' do
  36. 3 let( :event_name ) { 'after_create_concern' }
  37. 3 let( :arrow_line ) { ">>>>> #{event_name} >>>>>" }
  38. 1 context 'curation_concern concern responds to provenance_create' do
  39. 2 let( :curation_concern ) { CurationConcernWithProvLoggingMock.new }
  40. 1 before do
  41. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  42. 1 allow( curation_concern ).to receive( :provenance_create ).with( current_user: user, event_note: event_name )
  43. end
  44. 1 it do
  45. 1 Deepblue::EventHelper.after_create_concern_callback( curation_concern: curation_concern, user: user )
  46. 1 expect( Rails.logger ).to have_received( :debug ).with( arrow_line ).exactly( 4 ).times
  47. 1 expect( Rails.logger ).to have_received( :debug ).with( "#{event_name} >>>>> #{user} >>>>> #{curation_concern}" )
  48. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 5 ).times
  49. end
  50. end
  51. 1 context 'curation_concern concern does not respond to provenance_create' do
  52. 2 let( :curation_concern ) { CurationConcernMock.new }
  53. 1 before do
  54. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  55. end
  56. 1 it do
  57. 1 Deepblue::EventHelper.after_create_concern_callback( curation_concern: curation_concern, user: user )
  58. 1 expect( Rails.logger ).to have_received( :debug ).with( arrow_line ).exactly( 4 ).times
  59. 1 expect( Rails.logger ).to have_received( :debug ).with( "#{event_name} >>>>> #{user} >>>>> #{curation_concern}" )
  60. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 5 ).times
  61. end
  62. end
  63. end
  64. 1 describe '.after_create_fileset_callback' do
  65. 3 let( :event_name ) { 'after_create_fileset' }
  66. 3 let( :arrow_line ) { ">>>>> #{event_name} >>>>>" }
  67. 1 context 'file_set responds to provenance_create' do
  68. 2 let( :file_set ) { CurationConcernWithProvLoggingMock.new }
  69. 1 before do
  70. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  71. 1 allow( file_set ).to receive( :provenance_create ).with( current_user: user, event_note: event_name )
  72. end
  73. 1 it do
  74. 1 Deepblue::EventHelper.after_create_fileset_callback( file_set: file_set, user: user )
  75. 1 expect( Rails.logger ).to have_received( :debug ).with( arrow_line ).exactly( 4 ).times
  76. 1 expect( Rails.logger ).to have_received( :debug ).with( "#{event_name} >>>>> #{user} >>>>> #{file_set}" )
  77. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 5 ).times
  78. end
  79. end
  80. 1 context 'file_set does not respond to provenance_create' do
  81. 2 let( :file_set ) { CurationConcernMock.new }
  82. 1 before do
  83. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  84. end
  85. 1 it do
  86. 1 Deepblue::EventHelper.after_create_fileset_callback( file_set: file_set, user: user )
  87. 1 expect( Rails.logger ).to have_received( :debug ).with( arrow_line ).exactly( 4 ).times
  88. 1 expect( Rails.logger ).to have_received( :debug ).with( "#{event_name} >>>>> #{user} >>>>> #{file_set}" )
  89. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 5 ).times
  90. end
  91. end
  92. end
  93. end

spec/helpers/deepblue/logging_helper_spec.rb

100.0% lines covered

90 relevant lines. 90 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 RSpec.describe Deepblue::LoggingHelper, type: :helper do
  3. 1 describe '.bold_debug' do
  4. 5 let( :arrow_line ) { ">>>>>>>>>>" }
  5. 3 let( :msg ) { 'The message.' }
  6. 1 context 'with msg' do
  7. 1 before do
  8. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  9. end
  10. 1 it do
  11. 1 Deepblue::LoggingHelper.bold_debug( msg )
  12. 1 expect( Rails.logger ).to have_received( :debug ).with( arrow_line ).exactly( 2 ).times
  13. 1 expect( Rails.logger ).to have_received( :debug ).with( msg )
  14. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 3 ).times
  15. end
  16. end
  17. 1 context 'with msg and lines: 2' do
  18. 1 before do
  19. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  20. end
  21. 1 it do
  22. 1 Deepblue::LoggingHelper.bold_debug( msg, lines: 2 )
  23. 1 expect( Rails.logger ).to have_received( :debug ).with( arrow_line ).exactly( 4 ).times
  24. 1 expect( Rails.logger ).to have_received( :debug ).with( msg )
  25. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 5 ).times
  26. end
  27. end
  28. 1 context 'with msg as array' do
  29. 2 let( :msg_line_1 ) { "line 1" }
  30. 2 let( :msg_line_2 ) { "line 2" }
  31. 2 let( :msg_array ) { [ msg_line_1, msg_line_2 ] }
  32. 1 before do
  33. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  34. end
  35. 1 it do
  36. 1 Deepblue::LoggingHelper.bold_debug( msg_array )
  37. 1 expect( Rails.logger ).to have_received( :debug ).with( arrow_line ).exactly( 2 ).times
  38. 1 expect( Rails.logger ).to have_received( :debug ).with( msg_line_1 )
  39. 1 expect( Rails.logger ).to have_received( :debug ).with( msg_line_1 )
  40. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 4 ).times
  41. end
  42. end
  43. 1 context 'with msg as hash' do
  44. 2 let( :msg_key1 ) { :key1 }
  45. 2 let( :msg_key2 ) { :key2 }
  46. 2 let( :msg_value_1 ) { "value 1" }
  47. 2 let( :msg_value_2 ) { "value 2" }
  48. 2 let( :msg_hash ) { [ msg_key1 => msg_value_1, msg_key2 => msg_value_2 ] }
  49. 1 before do
  50. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  51. end
  52. 1 it do
  53. 1 Deepblue::LoggingHelper.bold_debug( msg_hash )
  54. 1 expect( Rails.logger ).to have_received( :debug ).with( arrow_line ).exactly( 2 ).times
  55. 1 expect( Rails.logger ).to have_received( :debug ).with( "#{msg_key1}: #{msg_value_1}" )
  56. 1 expect( Rails.logger ).to have_received( :debug ).with( "#{msg_key2}: #{msg_value_2}" )
  57. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 4 ).times
  58. end
  59. end
  60. # context 'with block msg' do
  61. # let( :block_msg ) { 'The block message.' }
  62. # before do
  63. # allow( Rails.logger ).to receive( :debug ).with( any_args )
  64. # end
  65. # it do
  66. # Deepblue::LoggingHelper.bold_debug( lines: 2 ) { block_msg }
  67. # expect( Rails.logger ).to have_received( :debug ).with( arrow_line ).exactly( 4 ).times
  68. # expect( Rails.logger ).to have_received( :debug ).with( block_msg )
  69. # expect( Rails.logger ).to have_received( :debug ).exactly( 5 ).times
  70. # end
  71. # end
  72. end
  73. 1 describe '.initialize_key_values' do
  74. 4 let( :event_note ) { 'the_event_note' }
  75. 6 let( :user_email ) { 'user@email.com' }
  76. 1 context 'parameters: user_email and event_note' do
  77. 1 subject do
  78. 3 lambda do |user_email, event_note|
  79. 3 Deepblue::LoggingHelper.initialize_key_values( user_email: user_email, event_note: event_note )
  80. end
  81. end
  82. 2 let( :result_both ) { { user_email: user_email, event_note: event_note } }
  83. 3 let( :result_no_event_note ) { { user_email: user_email } }
  84. 2 it { expect( subject.call( user_email, event_note ) ).to eq result_both }
  85. 2 it { expect( subject.call( user_email, '' ) ).to eq result_no_event_note }
  86. 2 it { expect( subject.call( user_email, nil ) ).to eq result_no_event_note }
  87. end
  88. 1 context 'parameters: user_email, event_note and added' do
  89. 3 let( :added1 ) { 'one' }
  90. 2 let( :added2 ) { 'two' }
  91. 2 let( :result1 ) { { user_email: user_email, event_note: event_note, added1: added1 } }
  92. 2 let( :result2 ) { { user_email: user_email, event_note: event_note, added1: added1, added2: added2 } }
  93. 1 it 'returns a hash containing user_email, event_note, and added1' do
  94. 1 expect( Deepblue::LoggingHelper.initialize_key_values( user_email: user_email,
  95. event_note: event_note,
  96. added1: added1 ) ).to eq result1
  97. end
  98. 1 it 'returns a hash containing user_email, event_note, added1, and added2' do
  99. 1 expect( Deepblue::LoggingHelper.initialize_key_values( user_email: user_email,
  100. event_note: event_note,
  101. added1: added1,
  102. added2: added2 ) ).to eq result2
  103. end
  104. end
  105. end
  106. 1 describe '.msg_to_log' do
  107. 3 let( :class_name ) { 'DataSet' }
  108. 3 let( :event ) { 'the_event' }
  109. 2 let( :event_note ) { 'the_event_note' }
  110. 2 let( :blank_event_note ) { '' }
  111. 3 let( :id ) { 'id1234' }
  112. 3 let( :timestamp ) { Time.now.to_formatted_s(:db ) }
  113. 3 let( :time_zone ) { DateTime.now.zone }
  114. 1 context 'parms without added' do
  115. 2 let( :key_values ) { { event: event,
  116. event_note: event_note,
  117. timestamp: timestamp,
  118. time_zone: time_zone,
  119. class_name: class_name,
  120. id: id } }
  121. 2 let( :json ) { ActiveSupport::JSON.encode key_values }
  122. 2 let( :result1 ) { "#{timestamp} #{event}/#{event_note}/#{class_name}/#{id} #{json}" }
  123. 1 it do
  124. 1 expect( Deepblue::LoggingHelper.msg_to_log( class_name: class_name,
  125. event: event,
  126. event_note: event_note,
  127. id: id,
  128. timestamp: timestamp,
  129. time_zone: time_zone ) ).to eq result1
  130. end
  131. end
  132. 1 context 'parms, blank event_note, without added' do
  133. 2 let( :key_values ) { { event: event, timestamp: timestamp, time_zone: time_zone, class_name: class_name, id: id } }
  134. 2 let( :json ) { ActiveSupport::JSON.encode key_values }
  135. 2 let( :result1 ) { "#{timestamp} #{event}//#{class_name}/#{id} #{json}" }
  136. 1 it do
  137. 1 expect( Deepblue::LoggingHelper.msg_to_log( class_name: class_name,
  138. event: event,
  139. event_note: blank_event_note,
  140. id: id,
  141. timestamp: timestamp,
  142. time_zone: time_zone ) ).to eq result1
  143. end
  144. end
  145. end
  146. 1 describe '.system_as_current_user' do
  147. 2 subject { Deepblue::LoggingHelper.system_as_current_user }
  148. 2 it { expect( subject ).to eq 'Deepblue' }
  149. end
  150. end

spec/helpers/deepblue/provenance_helper_spec.rb

100.0% lines covered

293 relevant lines. 293 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 RSpec.describe Deepblue::ProvenanceHelper, type: :helper do
  3. 1 describe 'constants' do
  4. 1 it do
  5. 1 expect( Deepblue::JsonLoggerHelper::TIMESTAMP_FORMAT ).to eq '\d\d\d\d\-\d\d\-\d\d \d\d:\d\d:\d\d'
  6. 1 expect( Deepblue::JsonLoggerHelper::RE_TIMESTAMP_FORMAT.source ).to eq '^\d\d\d\d\-\d\d\-\d\d \d\d:\d\d:\d\d$'
  7. 1 expect( Deepblue::JsonLoggerHelper::RE_LOG_LINE.source ).to \
  8. eq '^(\d\d\d\d\-\d\d\-\d\d \d\d:\d\d:\d\d) ([^/]+)/([^/]*)/([^/]+)/([^/ ]*) (.*)$'
  9. 1 expect( Deepblue::JsonLoggerHelper::PREFIX_UPDATE_ATTRIBUTE ).to eq 'UpdateAttribute_'
  10. end
  11. end
  12. 1 describe '.echo_to_rails_logger' do
  13. 2 subject { Deepblue::ProvenanceHelper.echo_to_rails_logger }
  14. 2 it { expect( subject ).to eq true }
  15. end
  16. 1 describe '.form_params_to_update_attribute_key_values' do
  17. 4 let( :authoremail ) { 'authoremail@umich.edu' }
  18. 4 let( :creator ) { 'Creator, A' }
  19. 1 let( :current_user ) { 'user@umich.edu' }
  20. 4 let( :date_created ) { '2018-02-28' }
  21. 4 let( :depositor ) { authoremail }
  22. 4 let( :description ) { 'The Description' }
  23. 1 let( :id ) { '0123458678' }
  24. 4 let( :methodology ) { 'The Methodology' }
  25. 2 let( :methodology_new ) { 'The New Methodology' }
  26. 4 let( :rights_license ) { 'The Rights License' }
  27. 4 let( :subject_discipline ) { 'The Subject Discipline' }
  28. 4 let( :title ) { 'The Title' }
  29. 3 let( :visibility_private ) { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE }
  30. 4 let( :visibility_public ) { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC }
  31. 1 let( :curation_concern ) do
  32. 3 DataSet.new( authoremail: authoremail,
  33. title: [title],
  34. creator: [creator],
  35. date_created: date_created,
  36. depositor: depositor,
  37. description: [description],
  38. methodology: methodology,
  39. rights_license: rights_license,
  40. subject_discipline: [subject_discipline],
  41. visibility: visibility_public )
  42. end
  43. 1 context 'No changes' do
  44. 1 let( :form_params ) do
  45. 1 { "title": [title, ""],
  46. "creator": [creator, ""],
  47. "authoremail": authoremail,
  48. "methodology": methodology,
  49. "description": [description, ""],
  50. "rights_license": rights_license,
  51. "subject_discipline": [subject_discipline, ""],
  52. "fundedby": "",
  53. "fundedby_other": "",
  54. "grantnumber": "",
  55. "keyword": [""],
  56. "language": [""],
  57. "referenced_by": [""],
  58. "member_of_collection_ids": "",
  59. "find_child_work": "",
  60. "permissions_attributes": { "0": { "access": "edit", "id": "197055dd-3e5e-4714-9878-8620f2195428/39/2e/47/ca/392e47ca-b01b-4c3f-afb9-9ddb537fdacc" } },
  61. "visibility_during_embargo": "restricted",
  62. "embargo_release_date": "2018-06-30",
  63. "visibility_after_embargo": "restricted",
  64. "visibility_during_lease": "open",
  65. "lease_expiration_date": "2018-06-30",
  66. "visibility_after_lease": "open",
  67. "visibility": visibility_private,
  68. "version": "W/\"591319c1fdd3c69832f55e8fbbef903a4a0381a5\"",
  69. "date_coverage": "" }
  70. end
  71. 2 let( :expected_attr_key_values ) { {:UpdateAttribute_visibility=>{:attribute=>:visibility, :new_value=>"restricted", :old_value=>"open"}} }
  72. 1 it do
  73. 1 attr_key_values = Deepblue::ProvenanceHelper.form_params_to_update_attribute_key_values( curation_concern: curation_concern,
  74. form_params: form_params )
  75. 1 expect( attr_key_values ).to eq expected_attr_key_values
  76. end
  77. end
  78. 1 context 'Only visibility change.' do
  79. 1 let( :form_params ) do
  80. 1 { "title": [title, ""],
  81. "creator": [creator, ""],
  82. "authoremail": authoremail,
  83. "methodology": methodology,
  84. "description": [description, ""],
  85. "rights_license": rights_license,
  86. "subject_discipline": [subject_discipline, ""],
  87. "fundedby": "",
  88. "fundedby_other": "",
  89. "grantnumber": "",
  90. "keyword": [""],
  91. "language": [""],
  92. "referenced_by": [""],
  93. "member_of_collection_ids": "",
  94. "find_child_work": "",
  95. "permissions_attributes": { "0": { "access": "edit", "id": "197055dd-3e5e-4714-9878-8620f2195428/39/2e/47/ca/392e47ca-b01b-4c3f-afb9-9ddb537fdacc" } },
  96. "visibility_during_embargo": "restricted",
  97. "embargo_release_date": "2018-06-30",
  98. "visibility_after_embargo": "open",
  99. "visibility_during_lease": "open",
  100. "lease_expiration_date": "2018-06-30",
  101. "visibility_after_lease": "restricted",
  102. "visibility": visibility_private,
  103. "version": "W/\"591319c1fdd3c69832f55e8fbbef903a4a0381a5\"",
  104. "date_coverage": "" }
  105. end
  106. 2 let( :expected_attr_key_values ) { {:UpdateAttribute_visibility=>{:attribute=>:visibility, :new_value=>"restricted", :old_value=>"open"}} }
  107. 1 it do
  108. 1 attr_key_values = Deepblue::ProvenanceHelper.form_params_to_update_attribute_key_values( curation_concern: curation_concern,
  109. form_params: form_params )
  110. 1 expect( attr_key_values ).to eq expected_attr_key_values
  111. end
  112. end
  113. 1 context 'methodology updated' do
  114. 1 let( :form_params ) do
  115. 1 { "title": [title, ""],
  116. "creator": [creator, ""],
  117. "authoremail": authoremail,
  118. "methodology": methodology_new,
  119. "description": [description, ""],
  120. "rights_license": rights_license,
  121. "subject_discipline": [subject_discipline, ""],
  122. "fundedby": "",
  123. "fundedby_other": "",
  124. "grantnumber": "",
  125. "keyword": [""],
  126. "language": [""],
  127. "referenced_by": [""],
  128. "member_of_collection_ids": "",
  129. "find_child_work": "",
  130. "permissions_attributes": { "0": { "access": "edit", "id": "197055dd-3e5e-4714-9878-8620f2195428/39/2e/47/ca/392e47ca-b01b-4c3f-afb9-9ddb537fdacc" } },
  131. "visibility_during_embargo": "restricted",
  132. "embargo_release_date": "2018-06-30",
  133. "visibility_after_embargo": "open",
  134. "visibility_during_lease": "open",
  135. "lease_expiration_date": "2018-06-30",
  136. "visibility_after_lease": "open",
  137. "visibility": visibility_public,
  138. "version": "W/\"591319c1fdd3c69832f55e8fbbef903a4a0381a5\"",
  139. "date_coverage": "" }
  140. end
  141. 2 let( :expected_attr_key_values ) { { UpdateAttribute_methodology: { attribute: :methodology, old_value: methodology, new_value: methodology_new } } }
  142. 1 it do
  143. 1 attr_key_values = Deepblue::ProvenanceHelper.form_params_to_update_attribute_key_values( curation_concern: curation_concern,
  144. form_params: form_params )
  145. 1 expect( attr_key_values ).to eq expected_attr_key_values
  146. end
  147. end
  148. end
  149. 1 describe '.initialize_prov_key_values' do
  150. 4 let( :event_note ) { 'the_event_note' }
  151. 6 let( :user_email ) { 'user@email.com' }
  152. 1 context 'parameters: user_email and event_note' do
  153. 1 subject do
  154. 3 lambda do |user_email, event_note|
  155. 3 Deepblue::ProvenanceHelper.logger_initialize_key_values(user_email: user_email, event_note: event_note )
  156. end
  157. end
  158. 2 let( :result_both ) { { user_email: user_email, event_note: event_note } }
  159. 3 let( :result_no_event_note ) { { user_email: user_email } }
  160. 2 it { expect( subject.call( user_email, event_note ) ).to eq result_both }
  161. 2 it { expect( subject.call( user_email, '' ) ).to eq result_no_event_note }
  162. 2 it { expect( subject.call( user_email, nil ) ).to eq result_no_event_note }
  163. end
  164. 1 context 'parameters: user_email, event_note and added' do
  165. 3 let( :added1 ) { 'one' }
  166. 2 let( :added2 ) { 'two' }
  167. 2 let( :result1 ) { { user_email: user_email, event_note: event_note, added1: added1 } }
  168. 2 let( :result2 ) { { user_email: user_email, event_note: event_note, added1: added1, added2: added2 } }
  169. 1 it 'returns a hash containing user_email, event_note, and added1' do
  170. 1 expect( Deepblue::ProvenanceHelper.logger_initialize_key_values(user_email: user_email,
  171. event_note: event_note,
  172. added1: added1 ) ).to eq result1
  173. end
  174. 1 it 'returns a hash containing user_email, event_note, added1, and added2' do
  175. 1 expect( Deepblue::ProvenanceHelper.logger_initialize_key_values(user_email: user_email,
  176. event_note: event_note,
  177. added1: added1,
  178. added2: added2 ) ).to eq result2
  179. end
  180. end
  181. end
  182. 1 describe '.msg_to_log' do
  183. 3 let( :class_name ) { 'DataSet' }
  184. 3 let( :event ) { 'the_event' }
  185. 2 let( :event_note ) { 'the_event_note' }
  186. 2 let( :blank_event_note ) { '' }
  187. 3 let( :id ) { 'id1234' }
  188. 3 let( :timestamp ) { Time.now.to_formatted_s(:db ) }
  189. 3 let( :time_zone ) { DateTime.now.zone }
  190. 1 context 'parms without added' do
  191. 2 let( :key_values ) { { event: event,
  192. event_note: event_note,
  193. timestamp: timestamp,
  194. time_zone: time_zone,
  195. class_name: class_name,
  196. id: id } }
  197. 2 let( :json ) { ActiveSupport::JSON.encode key_values }
  198. 2 let( :result1 ) { "#{timestamp} #{event}/#{event_note}/#{class_name}/#{id} #{json}" }
  199. 1 it do
  200. 1 expect( Deepblue::ProvenanceHelper.msg_to_log( class_name: class_name,
  201. event: event,
  202. event_note: event_note,
  203. id: id,
  204. timestamp: timestamp,
  205. time_zone: time_zone ) ).to eq result1
  206. end
  207. end
  208. 1 context 'parms, blank event_note, without added' do
  209. 2 let( :key_values ) { { event: event, timestamp: timestamp, time_zone: time_zone, class_name: class_name, id: id } }
  210. 2 let( :json ) { ActiveSupport::JSON.encode key_values }
  211. 2 let( :result1 ) { "#{timestamp} #{event}//#{class_name}/#{id} #{json}" }
  212. 1 it do
  213. 1 expect( Deepblue::ProvenanceHelper.msg_to_log( class_name: class_name,
  214. event: event,
  215. event_note: blank_event_note,
  216. id: id,
  217. timestamp: timestamp,
  218. time_zone: time_zone ) ).to eq result1
  219. end
  220. end
  221. end
  222. 1 describe '.log' do
  223. 2 let( :added1 ) { 'one' }
  224. 2 let( :added2 ) { 'two' }
  225. 3 let( :class_name ) { 'DataSet' }
  226. 2 let( :class_name_default ) { 'UnknownClass' }
  227. 3 let( :event ) { 'the_event' }
  228. 2 let( :event_default ) { 'unknown' }
  229. 3 let( :event_note ) { 'the_event_note' }
  230. 2 let( :event_note_default ) { '' }
  231. 1 let( :blank_event_note ) { '' }
  232. 3 let( :id ) { 'id1234' }
  233. 2 let( :id_default ) { 'unknown_id' }
  234. 1 let( :timestamp ) { Time.now.to_formatted_s(:db ) }
  235. 2 let( :time_zone ) { DateTime.now.zone }
  236. 1 context 'no parms' do
  237. 1 it do
  238. 1 prov_logger_received = nil
  239. 2 allow( PROV_LOGGER ).to receive( :info ) { |msg| prov_logger_received = msg }
  240. 1 before = Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now
  241. 1 Deepblue::ProvenanceHelper.log
  242. 1 after = Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now
  243. 1 expect( prov_logger_received ).to be_a String
  244. rv_timestamp,
  245. rv_event,
  246. rv_event_note,
  247. rv_class_name,
  248. rv_id,
  249. 1 rv_key_values = Deepblue::ProvenanceHelper.parse_log_line prov_logger_received
  250. 1 expect( rv_timestamp ).to be_between( before, after )
  251. 1 expect( rv_event ).to eq event_default
  252. 1 expect( rv_event_note ).to eq event_note_default
  253. 1 expect( rv_class_name ).to eq class_name_default
  254. 1 expect( rv_id ).to eq id_default
  255. 1 expect( rv_key_values['timestamp'] ).to be_between( before, after )
  256. 1 expect( rv_key_values['time_zone'] ).to eq time_zone
  257. 1 expect( rv_key_values['event'] ).to eq event_default
  258. # expect( rv_key_values['event_note'] ).to eq event_note_default
  259. 1 expect( rv_key_values['class_name'] ).to eq class_name_default
  260. 1 expect( rv_key_values['id'] ).to eq id_default
  261. 1 expect( rv_key_values.size ).to eq 5
  262. end
  263. end
  264. 1 context 'parms specified, no added' do
  265. 2 let( :timestamp ) { Deepblue::ProvenanceHelper.to_log_format_timestamp( 5.minutes.ago ) }
  266. 2 let( :time_zone ) { DateTime.now.zone }
  267. 1 it do
  268. 1 prov_logger_received = nil
  269. 2 allow( PROV_LOGGER ).to receive( :info ) { |msg| prov_logger_received = msg }
  270. 1 Deepblue::ProvenanceHelper.log( class_name: class_name,
  271. event: event,
  272. event_note: event_note,
  273. id: id,
  274. timestamp: timestamp,
  275. time_zone: time_zone )
  276. 1 expect( prov_logger_received ).to be_a String
  277. rv_timestamp,
  278. rv_event,
  279. rv_event_note,
  280. rv_class_name,
  281. rv_id,
  282. 1 rv_key_values = Deepblue::ProvenanceHelper.parse_log_line prov_logger_received
  283. 1 expect( rv_timestamp ).to eq timestamp
  284. 1 expect( rv_event ).to eq event
  285. 1 expect( rv_event_note ).to eq event_note
  286. 1 expect( rv_class_name ).to eq class_name
  287. 1 expect( rv_id ).to eq id
  288. 1 expect( rv_key_values['timestamp'] ).to eq timestamp
  289. 1 expect( rv_key_values['time_zone'] ).to eq time_zone
  290. 1 expect( rv_key_values['event'] ).to eq event
  291. 1 expect( rv_key_values['event_note'] ).to eq event_note
  292. 1 expect( rv_key_values['class_name'] ).to eq class_name
  293. 1 expect( rv_key_values['id'] ).to eq id
  294. 1 expect( rv_key_values.size ).to eq 6
  295. end
  296. end
  297. 1 context 'parms specified and added' do
  298. 2 let( :timestamp ) { Deepblue::ProvenanceHelper.to_log_format_timestamp( 5.minutes.ago ) }
  299. 2 let( :time_zone ) { DateTime.now.zone }
  300. 1 it do
  301. 1 prov_logger_received = nil
  302. 2 allow( PROV_LOGGER ).to receive( :info ) { |msg| prov_logger_received = msg }
  303. 1 Deepblue::ProvenanceHelper.log( class_name: class_name,
  304. event: event,
  305. event_note: event_note,
  306. id: id,
  307. timestamp: timestamp,
  308. time_zone: time_zone,
  309. added1: added1,
  310. added2: added2 )
  311. 1 expect( prov_logger_received ).to be_a String
  312. rv_timestamp,
  313. rv_event,
  314. rv_event_note,
  315. rv_class_name,
  316. rv_id,
  317. 1 rv_key_values = Deepblue::ProvenanceHelper.parse_log_line prov_logger_received
  318. 1 expect( rv_timestamp ).to eq timestamp
  319. 1 expect( rv_event ).to eq event
  320. 1 expect( rv_event_note ).to eq event_note
  321. 1 expect( rv_class_name ).to eq class_name
  322. 1 expect( rv_id ).to eq id
  323. 1 expect( rv_key_values['timestamp'] ).to eq timestamp
  324. 1 expect( rv_key_values['time_zone'] ).to eq time_zone
  325. 1 expect( rv_key_values['event'] ).to eq event
  326. 1 expect( rv_key_values['event_note'] ).to eq event_note
  327. 1 expect( rv_key_values['class_name'] ).to eq class_name
  328. 1 expect( rv_key_values['id'] ).to eq id
  329. 1 expect( rv_key_values['added1'] ).to eq added1
  330. 1 expect( rv_key_values['added2'] ).to eq added2
  331. 1 expect( rv_key_values.size ).to eq 8
  332. end
  333. end
  334. end
  335. 1 describe '.log_raw' do
  336. 2 let( :msg ) { 'The message.' }
  337. 1 before do
  338. 1 allow( PROV_LOGGER ).to receive( :info ).with( msg )
  339. end
  340. 1 it do
  341. 1 Deepblue::ProvenanceHelper.log_raw msg
  342. end
  343. end
  344. 1 describe '.parse_log_line' do
  345. 2 let( :added1 ) { 'one' }
  346. 2 let( :added2 ) { 'two' }
  347. 4 let( :class_name ) { 'DataSet' }
  348. 4 let( :event ) { 'the_event' }
  349. 3 let( :event_note ) { 'the_event_note' }
  350. 2 let( :blank_event_note ) { '' }
  351. 4 let( :id ) { 'id1234' }
  352. 4 let( :timestamp ) { Time.now.to_formatted_s(:db ) }
  353. 4 let( :time_zone ) { DateTime.now.zone }
  354. 1 context 'bad input raises error' do
  355. 1 it do
  356. 2 expect { Deepblue::ProvenanceHelper.parse_log_line( '' ) }.to \
  357. raise_error( Deepblue::LogParseError, "parse of log line failed: ''" )
  358. 2 expect { Deepblue::ProvenanceHelper.parse_log_line( nil ) }.to \
  359. raise_error( Deepblue::LogParseError, "parse of log line failed: ''" )
  360. 2 expect { Deepblue::ProvenanceHelper.parse_log_line( 'Some non-formatted line' ) }.to \
  361. raise_error( Deepblue::LogParseError, "parse of log line failed: 'Some non-formatted line'" )
  362. end
  363. end
  364. 1 context 'parms and added parms' do
  365. 2 let( :before ) { Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now }
  366. 2 let( :line ) { Deepblue::ProvenanceHelper.msg_to_log( class_name: class_name,
  367. event: event,
  368. event_note: event_note,
  369. id: id,
  370. timestamp: timestamp,
  371. time_zone: time_zone,
  372. added1: added1,
  373. added2: added2 ) }
  374. 2 let( :after ) { Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now }
  375. 1 it do
  376. rv_timestamp,
  377. rv_event,
  378. rv_event_note,
  379. rv_class_name,
  380. rv_id,
  381. 1 rv_key_values = Deepblue::ProvenanceHelper.parse_log_line line
  382. 1 expect( rv_timestamp ).to be_between( before, after )
  383. 1 expect( rv_event ).to eq event
  384. 1 expect( rv_event_note ).to eq event_note
  385. 1 expect( rv_class_name ).to eq class_name
  386. 1 expect( rv_id ).to eq id
  387. 1 expect( rv_key_values['timestamp'] ).to be_between( before, after )
  388. 1 expect( rv_key_values['time_zone'] ).to eq time_zone
  389. 1 expect( rv_key_values['event'] ).to eq event
  390. 1 expect( rv_key_values['event_note'] ).to eq event_note
  391. 1 expect( rv_key_values['class_name'] ).to eq class_name
  392. 1 expect( rv_key_values['id'] ).to eq id
  393. 1 expect( rv_key_values['added1'] ).to eq added1
  394. 1 expect( rv_key_values['added2'] ).to eq added2
  395. 1 expect( rv_key_values.size ).to eq 8
  396. end
  397. end
  398. 1 context 'parms without added' do
  399. 2 let( :before ) { Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now }
  400. 2 let( :line ) { Deepblue::ProvenanceHelper.msg_to_log( class_name: class_name,
  401. event: event,
  402. event_note: event_note,
  403. id: id,
  404. timestamp: timestamp,
  405. time_zone: time_zone ) }
  406. 2 let( :after ) { Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now }
  407. 1 it do
  408. rv_timestamp,
  409. rv_event,
  410. rv_event_note,
  411. rv_class_name,
  412. rv_id,
  413. 1 rv_key_values = Deepblue::ProvenanceHelper.parse_log_line line
  414. 1 expect( rv_timestamp ).to be_between( before, after )
  415. 1 expect( rv_event ).to eq event
  416. 1 expect( rv_event_note ).to eq event_note
  417. 1 expect( rv_class_name ).to eq class_name
  418. 1 expect( rv_id ).to eq id
  419. 1 expect( rv_key_values['timestamp'] ).to be_between( before, after )
  420. 1 expect( rv_key_values['event'] ).to eq event
  421. 1 expect( rv_key_values['event_note'] ).to eq event_note
  422. 1 expect( rv_key_values['class_name'] ).to eq class_name
  423. 1 expect( rv_key_values['id'] ).to eq id
  424. 1 expect( rv_key_values.size ).to eq 6
  425. end
  426. end
  427. 1 context 'parms without added and blank event note' do
  428. 2 let( :before ) { Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now }
  429. 2 let( :line ) { Deepblue::ProvenanceHelper.msg_to_log( class_name: class_name,
  430. event: event,
  431. event_note: blank_event_note,
  432. id: id,
  433. timestamp: timestamp,
  434. time_zone: time_zone ) }
  435. 2 let( :after ) { Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now }
  436. 1 it do
  437. rv_timestamp,
  438. rv_event,
  439. rv_event_note,
  440. rv_class_name,
  441. rv_id,
  442. 1 rv_key_values = Deepblue::ProvenanceHelper.parse_log_line line
  443. 1 expect( rv_timestamp ).to be_between( before, after )
  444. 1 expect( rv_event ).to eq event
  445. 1 expect( rv_event_note ).to eq blank_event_note
  446. 1 expect( rv_class_name ).to eq class_name
  447. 1 expect( rv_id ).to eq id
  448. 1 expect( rv_key_values['timestamp'] ).to be_between( before, after )
  449. 1 expect( rv_key_values['time_zone'] ).to eq time_zone
  450. 1 expect( rv_key_values['event'] ).to eq event
  451. # expect( rv_key_values['event_note'] ).to eq event_note
  452. 1 expect( rv_key_values['class_name'] ).to eq class_name
  453. 1 expect( rv_key_values['id'] ).to eq id
  454. 1 expect( rv_key_values.size ).to eq 5
  455. end
  456. end
  457. end
  458. 1 describe '.system_as_current_user' do
  459. 2 subject { Deepblue::ProvenanceHelper.system_as_current_user }
  460. 2 it { expect( subject ).to eq 'Deepblue' }
  461. end
  462. 1 describe '.timestamp_now' do
  463. 1 context 'is formatted correctly' do
  464. 1 it do
  465. 1 expect( Deepblue::ProvenanceHelper.timestamp_now ).to match '^\d\d\d\d\-\d\d\-\d\d \d\d:\d\d:\d\d$'
  466. end
  467. end
  468. 1 context 'is now' do
  469. 2 let( :before ) { Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now }
  470. 2 let( :timestamp_now ) { Deepblue::ProvenanceHelper.timestamp_now }
  471. 2 let( :after ) { Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now }
  472. 1 it do
  473. 1 expect( timestamp_now ).to be_between( before, after )
  474. end
  475. end
  476. end
  477. 1 describe '.to_log_format_timestamp' do
  478. 4 let( :time_now ) { Time.now }
  479. 2 let( :timestamp_now ) { time_now.to_formatted_s( :db ) }
  480. 4 let( :timestamp_re ) { '^\d\d\d\d\-\d\d\-\d\d \d\d:\d\d:\d\d$' }
  481. 1 context 'for correctly formatted string' do
  482. 1 it do
  483. 1 expect( Deepblue::ProvenanceHelper.to_log_format_timestamp( timestamp_now ) ).to match timestamp_re
  484. end
  485. end
  486. 1 context 'for correctly Time' do
  487. 1 it do
  488. 1 expect( Deepblue::ProvenanceHelper.to_log_format_timestamp( time_now ) ).to match timestamp_re
  489. end
  490. end
  491. 1 context 'for correctly different format string' do
  492. 1 it do
  493. 1 expect( Deepblue::ProvenanceHelper.to_log_format_timestamp( time_now.to_s ) ).to match timestamp_re
  494. end
  495. end
  496. end
  497. 1 describe '.update_attribute_key_values' do
  498. 2 let( :authoremail ) { 'authoremail@umich.edu' }
  499. 2 let( :creator ) { [ 'Creator, A' ] }
  500. 1 let( :current_user ) { 'user@umich.edu' }
  501. 2 let( :date_created ) { '2018-02-28' }
  502. 2 let( :depositor ) { authoremail }
  503. 2 let( :description ) { [ 'The Description' ] }
  504. 1 let( :id ) { '0123458678' }
  505. 2 let( :methodology_new ) { 'The New Methodology' }
  506. 2 let( :methodology_old ) { 'The Old Methodology' }
  507. 2 let( :rights_license ) { 'The Rights License' }
  508. 2 let( :title ) { [ 'The Title' ] }
  509. 2 let( :subject_discipline ) { 'The Subject Discipline' }
  510. 1 let( :visibility_private ) { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE }
  511. 2 let( :visibility_public ) { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC }
  512. 1 let( :curation_concern ) do
  513. 1 DataSet.new( authoremail: authoremail,
  514. title: title,
  515. creator: creator,
  516. date_created: date_created,
  517. depositor: depositor,
  518. description: description,
  519. methodology: methodology_new,
  520. rights_license: rights_license,
  521. subject_discipline: [subject_discipline],
  522. visibility: visibility_public )
  523. end
  524. 2 let( :update_attr_key_values ) { { UpdateAttribute_methodology: { attribute: :methodology, old_value: methodology_old, new_value: 'some value from form' } } }
  525. 1 it do
  526. 1 updated = Deepblue::ProvenanceHelper.update_attribute_key_values( curation_concern: curation_concern,
  527. update_attr_key_values: update_attr_key_values )
  528. # puts ActiveSupport::JSON.encode updated
  529. # updated = updated[:update_attr_key_values]
  530. 1 expect( updated.size ).to be 1
  531. 1 expect( updated.key?(:UpdateAttribute_methodology) ).to be true
  532. 1 expect( updated[:UpdateAttribute_methodology][:attribute] ).to eq :methodology
  533. 1 expect( updated[:UpdateAttribute_methodology][:old_value] ).to eq methodology_old
  534. 1 expect( updated[:UpdateAttribute_methodology][:new_value] ).to eq methodology_new
  535. end
  536. end
  537. end

spec/integration/clamav_daemon_spec.rb

62.5% lines covered

16 relevant lines. 10 lines covered and 6 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'umich_clamav_daemon_scanner'
  3. 1 RSpec.describe UMichClamAVDaemonScanner do
  4. 1 let(:clamd_running) { !!/\S/.match(`pgrep clamd`) }
  5. 4 let(:basic_av_connection) { described_class.new(__FILE__) }
  6. 1 it "can scan a harmless file" do
  7. 1 skip("ClamAV Daemon not running") unless basic_av_connection.alive?
  8. scanner = described_class.new(__FILE__)
  9. expect(scanner.scan_response).to be_a(ClamAV::SuccessResponse)
  10. end
  11. 1 it "reports an error on a bad file (directory in this case)" do
  12. 1 skip("ClamAV Daemon not running") unless basic_av_connection.alive?
  13. scanner = described_class.new(__dir__)
  14. expect(scanner.scan_response).to be_a(ClamAV::ErrorResponse)
  15. end
  16. 1 it "errors out if the file doesn't exist" do
  17. 1 skip("ClamAV Daemon not running") unless basic_av_connection.alive?
  18. scanner = described_class.new('asdfadsfasdfasdfasdf')
  19. expect { scanner.infected? }.to raise_error(RuntimeError, /Can't open file/)
  20. end
  21. end

spec/jobs/about_to_expire_embargoes_job_spec.rb

100.0% lines covered

64 relevant lines. 64 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 class MockJob
  3. 1 def run( )
  4. end
  5. end
  6. 1 RSpec.describe Hyrax::ApplicationJob::AboutToExpireEmbargoesJob do
  7. 1 describe "#perform" do
  8. 1 jobObject = MockJob.new
  9. 1 before {
  10. 3 allow(Deepblue::LoggingHelper).to receive(:here).and_return "here"
  11. 3 allow(Deepblue::LoggingHelper).to receive(:called_from).and_return "called from"
  12. 3 allow(Deepblue::LoggingHelper).to receive(:obj_class).with('class', an_instance_of(AboutToExpireEmbargoesJob)).and_return "bundt"
  13. 3 allow(Deepblue::LoggingHelper).to receive(:obj_class).with( 'args', ["cake"] ).and_return "frosting"
  14. 3 allow(Deepblue::LoggingHelper).to receive(:bold_debug).with([ "here", "called from", "bundt", "args=[\"cake\"]", "frosting", "" ])
  15. 3 allow(Deepblue::SchedulerHelper).to receive(:log).with( class_name: "AboutToExpireEmbargoesJob", event: "about_to_expire_embargoes" )
  16. 3 allow(Deepblue::LoggingHelper).to receive(:obj_class).with('options', {"cake"=>nil}).and_return "frosting"
  17. 3 allow(Deepblue::LoggingHelper).to receive(:bold_debug).with([[ "here", "options={\"cake\"=>nil}", "frosting", "" ]])
  18. 3 allow(subject).to receive(:job_options_value).with({"cake"=>nil}, {key: 'email_owner', default_value: true} ).and_return "email_owner"
  19. 3 allow(subject).to receive(:job_options_value).with({"cake"=>nil}, {key: 'expiration_lead_days'} ).and_return "lead_days"
  20. 3 allow(subject).to receive(:job_options_value).with({"cake"=>nil}, {key: 'skip_file_sets', default_value: true} ).and_return "skipping"
  21. 3 allow(subject).to receive(:job_options_value).with({"cake"=>nil}, {key: 'test_mode', default_value: false} ).and_return "la mode"
  22. }
  23. 1 context "when verbose" do
  24. 1 before {
  25. 1 allow(subject).to receive(:job_options_value).with({"cake"=>nil}, {:key=>"verbose", :default_value=>false} ).and_return true
  26. 1 allow(Deepblue::LoggingHelper).to receive(:debug).with( "verbose=true" )
  27. 1 allow(Deepblue::LoggingHelper).to receive(:debug).with( "email_owner=email_owner" )
  28. 1 allow(Deepblue::LoggingHelper).to receive(:debug).with( "expiration_lead_days=lead_days" )
  29. 1 allow(Deepblue::LoggingHelper).to receive(:debug).with( "@skip_file_sets=skipping")
  30. 1 allow(Deepblue::LoggingHelper).to receive(:debug).with( "test_mode=la mode")
  31. 1 allow(Deepblue::AboutToExpireEmbargoesService).to receive(:new).with( email_owner: "email_owner",
  32. expiration_lead_days: "lead_days",
  33. skip_file_sets: "skipping",
  34. test_mode: "la mode",
  35. verbose: true ).and_return(jobObject)
  36. 1 allow(jobObject).to receive(:run)
  37. }
  38. 1 it "calls Deepblue helper methods and logging debug method" do
  39. 1 expect(Deepblue::LoggingHelper).to receive(:bold_debug).with([ "here", "called from", "bundt", "args=[\"cake\"]", "frosting", "" ])
  40. 1 expect(Deepblue::SchedulerHelper).to receive(:log).with( class_name: "AboutToExpireEmbargoesJob", event: "about_to_expire_embargoes" )
  41. 1 expect(Deepblue::LoggingHelper).to receive(:bold_debug).with([ "here", "options={\"cake\"=>nil}", "frosting", "" ])
  42. 1 expect(subject).to receive(:job_options_value).with({"cake"=>nil}, {:key=>"verbose", :default_value=>false} ).and_return true
  43. 1 expect(Deepblue::LoggingHelper).to receive(:debug).with( "verbose=true" )
  44. 1 expect(subject).to receive(:job_options_value).with({"cake"=>nil}, {key: 'email_owner', default_value: true} ).and_return "email_owner"
  45. 1 expect(Deepblue::LoggingHelper).to receive(:debug).with( "email_owner=email_owner" )
  46. 1 expect(subject).to receive(:job_options_value).with({"cake"=>nil}, {key: 'expiration_lead_days'} ).and_return "lead_days"
  47. 1 expect(Deepblue::LoggingHelper).to receive(:debug).with( "expiration_lead_days=lead_days" )
  48. 1 expect(subject).to receive(:job_options_value).with({"cake"=>nil}, {key: 'skip_file_sets', default_value: true} ).and_return "skipping"
  49. 1 expect(Deepblue::LoggingHelper).to receive(:debug).with( "@skip_file_sets=skipping")
  50. 1 expect(subject).to receive(:job_options_value).with({"cake"=>nil}, {key: 'test_mode', default_value: false} ).and_return "la mode"
  51. 1 expect(Deepblue::LoggingHelper).to receive(:debug).with( "test_mode=la mode")
  52. 1 expect(Deepblue::AboutToExpireEmbargoesService).to receive(:new).with( email_owner: "email_owner",
  53. expiration_lead_days: "lead_days",
  54. skip_file_sets: "skipping",
  55. test_mode: "la mode",
  56. verbose: true ).and_return(jobObject)
  57. 1 subject.perform "cake"
  58. end
  59. end
  60. 1 context "when not verbose" do
  61. 1 before {
  62. 1 allow(subject).to receive(:job_options_value).with({"cake"=>nil}, {:key=>"verbose", :default_value=>false} ).and_return false
  63. 1 allow(Deepblue::LoggingHelper).to receive(:debug).with( "verbose=false" )
  64. 1 allow(Deepblue::AboutToExpireEmbargoesService).to receive(:new).with( email_owner: "email_owner",
  65. expiration_lead_days: "lead_days",
  66. skip_file_sets: "skipping",
  67. test_mode: "la mode",
  68. verbose: false ).and_return(jobObject)
  69. }
  70. 1 it "calls Deepblue helper methods" do
  71. 1 expect(Deepblue::LoggingHelper).to receive(:bold_debug).with([ "here", "called from", "bundt", "args=[\"cake\"]", "frosting", "" ])
  72. 1 expect(Deepblue::SchedulerHelper).to receive(:log).with( class_name: "AboutToExpireEmbargoesJob", event: "about_to_expire_embargoes" )
  73. 1 expect(Deepblue::LoggingHelper).to receive(:bold_debug).with([ "here", "options={\"cake\"=>nil}", "frosting", "" ])
  74. 1 expect(subject).to receive(:job_options_value).with({"cake"=>nil}, {:key=>"verbose", :default_value=>false} ).and_return false
  75. 1 expect(subject).to receive(:job_options_value).with({"cake"=>nil}, {key: 'email_owner', default_value: true} ).and_return "email_owner"
  76. 1 expect(subject).to receive(:job_options_value).with({"cake"=>nil}, {key: 'expiration_lead_days'} ).and_return "lead_days"
  77. 1 expect(subject).to receive(:job_options_value).with({"cake"=>nil}, {key: 'skip_file_sets', default_value: true} ).and_return "skipping"
  78. 1 expect(subject).to receive(:job_options_value).with({"cake"=>nil}, {key: 'test_mode', default_value: false} ).and_return "la mode"
  79. 1 expect(Deepblue::AboutToExpireEmbargoesService).to receive(:new).with( email_owner: "email_owner",
  80. expiration_lead_days: "lead_days",
  81. skip_file_sets: "skipping",
  82. test_mode: "la mode",
  83. verbose: false ).and_return(jobObject)
  84. 1 subject.perform "cake"
  85. end
  86. end
  87. 1 context "when exception occurs" do
  88. 1 it "catches exceptions" do
  89. 1 skip "Add a test"
  90. end
  91. end
  92. end
  93. end

spec/jobs/globus_copy_job_spec.rb

48.32% lines covered

149 relevant lines. 72 lines covered and 77 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'rails_helper'
  3. 1 require 'uri'
  4. 1 require_relative '../../app/mailers/deepblue_mailer'
  5. 1 RSpec.configure do |config|
  6. 1 config.filter_run_excluding globus_enabled: :true unless DeepBlueDocs::Application.config.globus_enabled
  7. end
  8. 1 class MailerMock
  9. 1 def deliver_now; end
  10. end
  11. # TODO: re-enable globus specs?
  12. 1 describe GlobusCopyJob, "GlobusJob globus_enabled: :true", globus_enabled: :true, skip: true do # rubocop:disable RSpec/DescribeMethod
  13. 1 let( :globus_dir ) { Pathname "/tmp/deepbluedata-globus" }
  14. 1 let( :globus_download_dir ) { globus_dir.join 'download' }
  15. 1 let( :target_name ) { "DeepBlueData_id321" }
  16. 1 let( :target_name_prep_dir ) { "#{GlobusJob.server_prefix(str: '_')}#{target_name}" }
  17. 1 let( :globus_prep_dir ) { globus_dir.join 'prep' }
  18. 1 let( :error_file ) { globus_prep_dir.join ".test.error.#{target_name}" }
  19. 1 let( :job_ready_file ) { globus_prep_dir.join ".test.ready.#{target_name}" }
  20. 1 let( :lock_file ) { globus_prep_dir.join ".test.lock.#{target_name}" }
  21. 1 let( :email_file ) { globus_prep_dir.join ".test.copy_job_emails.#{target_name}" }
  22. 1 describe "#perform" do
  23. 1 let( :user ) { FactoryBot.build(:user) }
  24. 1 let( :work ) { FactoryBot.build(:data_set, id: 'id321', title: ['test title'], user: user) }
  25. 1 let( :globus_download_ready_dir ) { globus_download_dir.join target_name }
  26. 1 let( :globus_download_ready_file1 ) { globus_download_ready_dir.join 'File01' }
  27. 1 let( :globus_download_ready_file2 ) { globus_download_ready_dir.join 'File02' }
  28. 1 let( :globus_download_ready_file_metadata ) { globus_download_ready_dir.join 'w_id321_metadata_report.txt' }
  29. 1 let( :file_set1 ) { FactoryBot.build(:file_set, label: 'File01', id: 'fs0001') }
  30. 1 let( :file_set2 ) { FactoryBot.build(:file_set, label: 'File02', id: 'fs0002') }
  31. 1 let( :file1 ) { Tempfile.new( "File01-" ) }
  32. 1 let( :file2 ) { Tempfile.new( "File02-" ) }
  33. 1 let( :uri1 ) { URI.join('file:///', file1.path.to_s ) }
  34. 1 let( :uri2 ) { URI.join('file:///', file2.path.to_s ) }
  35. 1 let( :ready_file ) { job_ready_file }
  36. 1 let( :log_prefix ) { "Globus: globus_copy_job" }
  37. 1 let( :lock_file_msg ) { "#{log_prefix} lock file #{lock_file}" }
  38. 1 let( :globus_prep_copy_dir ) { globus_prep_dir.join target_name_prep_dir }
  39. 1 let( :globus_prep_copy_tmp_dir ) { globus_prep_dir.join( target_name_prep_dir + '_tmp' ) }
  40. 1 let( :current_token ) { GlobusJob.era_token }
  41. 1 let( :user_email ) { "test@email.edu" }
  42. 1 let( :email_addresses ) { [ user_email ] }
  43. 1 let( :mailer ) { MailerMock.new }
  44. 1 context "when can acquire lock" do
  45. 1 before do
  46. allow( ActiveFedora::Base ).to receive( :find ).and_return( work )
  47. file_set1.define_singleton_method( :files ) do nil; end
  48. file_set2.define_singleton_method( :files ) do nil; end
  49. file1.define_singleton_method( :uri ) do nil; end
  50. file2.define_singleton_method( :uri ) do nil; end
  51. file1.define_singleton_method( :original_name ) do 'File01' end
  52. file2.define_singleton_method( :original_name ) do 'File02' end
  53. uri1.define_singleton_method( :value ) do nil; end
  54. uri2.define_singleton_method( :value ) do nil; end
  55. allow( file_set1 ).to receive( :files ).and_return( [file1] )
  56. allow( file_set2 ).to receive( :files ).and_return( [file2] )
  57. allow( file1 ).to receive( :uri ).and_return( uri1 )
  58. allow( file2 ).to receive( :uri ).and_return( uri2 )
  59. allow( uri1 ).to receive( :value ).and_return( file1.path )
  60. allow( uri2 ).to receive( :value ).and_return( file2.path )
  61. allow( work ).to receive( :file_sets ).and_return( [file_set1, file_set2] )
  62. File.delete error_file if File.exist? error_file
  63. File.delete lock_file if File.exist? lock_file
  64. # Dir.delete globus_prep_copy_dir if Dir.exist? globus_prep_copy_dir
  65. # Dir.delete globus_prep_copy_tmp_dir if Dir.exist? globus_prep_copy_tmp_dir
  66. allow( Rails.logger ).to receive( :debug )
  67. allow( Rails.logger ).to receive( :error )
  68. allow( DeepblueMailer ).to receive( :send_an_email ).with( any_args ).and_return( mailer )
  69. allow( mailer ).to receive( :deliver_now )
  70. end
  71. 1 it "calls globus block." do
  72. open( file1.path, 'w' ) { |f| f << "File01" << "\n" }
  73. open( file2.path, 'w' ) { |f| f << "File02" << "\n" }
  74. described_class.perform_now( "id321", user_email: user_email )
  75. # expect( Rails.logger ).to have_received( :debug ).with( 'bogus so we can look at the logger output' )
  76. file = '/tmp/deepbluedata-globus/prep/.test.error.DeepBlueData_id321'
  77. if File.exist? file
  78. puts ">>>>>>>>>>>>>>>>>>"
  79. puts "Error file exists:"
  80. open( file, 'r') { |f| puts f.readlines.join( "\n" ) }
  81. puts ">>>>>>>>>>>>>>>>>>"
  82. end
  83. expect( Rails.logger ).to have_received( :debug ).with( "#{log_prefix} lock file #{lock_file}" )
  84. expect( Rails.logger ).to have_received( :debug ).with( "#{log_prefix} writing lock token #{current_token} to #{lock_file}" )
  85. expect( Rails.logger ).to have_received( :debug ).with( "#{log_prefix} begin copy" )
  86. expect( Rails.logger ).to have_received( :debug ).with( "#{log_prefix} Starting export to #{globus_prep_copy_tmp_dir}" )
  87. expect( Rails.logger ).to have_received( :debug ).with( "#{log_prefix} copy complete" )
  88. # expect( Rails.logger ).to have_received( :debug ).with( 'bogus so we can look at the logger output' )
  89. # expect( Rails.logger ).to have_received( :error ).with( 'bogus so we can look at the logger output' )
  90. expect( Rails.logger ).not_to have_received( :error )
  91. expect( File.exist?(ready_file) ).to eq( true )
  92. expect( Dir.exist?(globus_download_ready_dir) ).to eq( true )
  93. expect( Dir.exist?(globus_prep_copy_dir) ).to eq( false )
  94. expect( Dir.exist?(globus_prep_copy_tmp_dir) ).to eq( false )
  95. expect( File.exist?(globus_download_ready_file1) ).to eq( true )
  96. expect( File.exist?(globus_download_ready_file2) ).to eq( true )
  97. expect( File.exist?(globus_download_ready_file_metadata) ).to eq( true )
  98. end
  99. 1 after do
  100. File.delete email_file if File.exist? email_file
  101. File.delete error_file if File.exist? error_file
  102. File.delete lock_file if File.exist? lock_file
  103. File.delete ready_file if File.exist? ready_file
  104. File.delete globus_download_ready_file1 if File.exist? globus_download_ready_file1
  105. File.delete globus_download_ready_file2 if File.exist? globus_download_ready_file2
  106. File.delete globus_download_ready_file_metadata if File.exist? globus_download_ready_file_metadata
  107. Dir.delete globus_download_ready_dir if Dir.exist? globus_download_ready_dir
  108. end
  109. end
  110. end
  111. 1 describe "#globus_do_copy?" do
  112. 1 let( :job ) { described_class.new }
  113. 1 let( :target_file_name ) { "targetfile" }
  114. 1 let( :prep_file_name ) { globus_prep_dir.join target_file_name }
  115. 1 before do
  116. prep_dir = globus_prep_dir
  117. job.define_singleton_method( :set_parms ) do
  118. @globus_concern_id = "id321"
  119. @globus_log_prefix = "Globus: "
  120. @target_prep_dir = prep_dir
  121. end
  122. job.set_parms
  123. end
  124. 1 context "when prep file exists" do
  125. 1 before do
  126. allow( File ).to receive( :exist? ).with( prep_file_name ).and_return( true )
  127. msg = "Globus: skipping copy because #{prep_file_name} already exists"
  128. allow(Rails.logger).to receive(:debug) { :failure }
  129. allow( Rails.logger ).to receive( :debug ).with( msg )
  130. end
  131. 1 it "returns false." do
  132. expect( job.send( :globus_do_copy?, target_file_name ) ).to eq( false )
  133. end
  134. end
  135. 1 context "when prep file does not exist" do
  136. 1 before do
  137. allow( File ).to receive( :exist? ).with( prep_file_name ).and_return( false )
  138. end
  139. 1 it "returns true." do
  140. expect( job.send( :globus_do_copy?, target_file_name ) ).to eq( true )
  141. end
  142. end
  143. end
  144. 1 describe "#globus_job_complete_file" do
  145. 1 let( :job ) { described_class.new }
  146. 1 before do
  147. job.define_singleton_method( :set_parms ) do @globus_concern_id = "id321"; end
  148. job.set_parms
  149. end
  150. 1 it "returns the ready file name." do
  151. expect( job.send( :globus_job_complete_file ) ).to eq( job_ready_file )
  152. end
  153. end
  154. 1 describe "#globus_job_complete?" do
  155. 1 let( :job ) { described_class.new }
  156. 1 let( :job_complete_dir ) { globus_download_dir.join 'DeepBlueData_id321' }
  157. 1 before do
  158. job.define_singleton_method( :set_parms ) do @globus_concern_id = "id321"; end
  159. job.set_parms
  160. end
  161. 1 context "when file exists" do
  162. 1 before do
  163. allow( Dir ).to receive( :exist? ).with( job_complete_dir ).and_return( true )
  164. end
  165. 1 it "return true." do
  166. expect( job.send( :globus_job_complete? ) ).to eq( true )
  167. end
  168. end
  169. 1 context "when file does not exist" do
  170. 1 before do
  171. allow( Dir ).to receive( :exist? ).with( job_complete_dir ).and_return( false )
  172. end
  173. 1 it "return true." do
  174. expect( job.send( :globus_job_complete? ) ).to eq( false )
  175. end
  176. end
  177. end
  178. # describe "#globus_notify_user" do
  179. # # TODO
  180. # end
  181. 1 describe "#globus_ready_file" do
  182. 1 let( :job ) { described_class.new }
  183. 1 before do
  184. job.define_singleton_method( :set_parms ) do @globus_concern_id = "id321"; end
  185. job.set_parms
  186. end
  187. 1 it "returns the ready file name." do
  188. expect( job.send( :globus_ready_file ) ).to eq( job_ready_file )
  189. end
  190. end
  191. end

spec/jobs/globus_job_spec.rb

52.29% lines covered

371 relevant lines. 194 lines covered and 177 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 RSpec.configure do |config|
  3. 1 config.filter_run_excluding globus_enabled: :true unless DeepBlueDocs::Application.config.globus_enabled
  4. end
  5. # TODO: re-enable globus specs?
  6. 1 describe GlobusJob, "GlobusJob globus_enabled: :true", globus_enabled: :true, skip: true do # rubocop:disable RSpec/DescribeMethod
  7. 1 let( :globus_dir ) { Pathname.new "/tmp/deepbluedata-globus" }
  8. 1 let( :globus_download_dir ) { globus_dir.join 'download' }
  9. 1 let( :globus_prep_dir ) { globus_dir.join 'prep' }
  10. 1 let( :globus_target_download_dir ) { globus_download_dir.join 'DeepBlueData_id321' }
  11. 1 let( :globus_target_prep_dir ) { globus_prep_dir.join "#{GlobusJob.server_prefix(str: '_')}DeepBlueData_id321" }
  12. 1 let( :globus_target_prep_tmp_dir ) { globus_prep_dir.join "#{GlobusJob.server_prefix(str: '_')}DeepBlueData_id321" }
  13. 1 let( :error_file ) { globus_prep_dir.join '.test.error.DeepBlueData_id321' }
  14. 1 let( :lock_file ) { globus_prep_dir.join '.test.lock.DeepBlueData_id321' }
  15. 1 describe "GlobusJob#copy_complete?" do
  16. 1 context "directory exists in download dir" do
  17. 1 before do
  18. allow( Dir ).to receive( :exist? ).with( globus_target_download_dir ).and_return( true )
  19. end
  20. 1 it "returns true." do expect( GlobusJob.copy_complete?( "id321" ) ).to eq( true ); end
  21. end
  22. end
  23. 1 describe "GlobusJob#external_url" do
  24. 1 it "returns a globus external url." do
  25. url = GlobusJob.external_url "id321"
  26. expect( url ).to eq( "https://app.globus.org/file-manager?origin_id=99d8c648-a9ff-11e7-aedd-22000a92523b&origin_path=%2Fdownload%2FDeepBlueData_id321%2F" )
  27. end
  28. end
  29. 1 describe "GlobusJob#files_prepping?" do
  30. 1 context "directory exists in prep dir" do
  31. 1 before do
  32. allow( Dir ).to receive( :exist? ).with( globus_target_download_dir ).and_return( false )
  33. allow( File ).to receive( :exist? ).with( error_file ).and_return( false )
  34. allow( GlobusJob ).to receive( :locked? ).with( "id321" ).and_return( true )
  35. end
  36. 1 it "returns true." do expect( GlobusJob.files_prepping?( "id321" ) ).to eq( true ); end
  37. end
  38. end
  39. 1 describe "GlobusJob#locked?" do
  40. 1 context "lock file does not exist" do
  41. 1 before do
  42. allow( File ).to receive( :exist? ).with( error_file ).and_return( false )
  43. allow( File ).to receive( :exist? ).with( lock_file ).and_return( false )
  44. end
  45. 1 it "returns true." do expect( GlobusJob.locked?( "id321" ) ).to eq( false ); end
  46. end
  47. ## see context "#globus_locked?" for more tests
  48. end
  49. 1 describe "GlobusJob#files_target_file_name" do
  50. 1 it "returns target file name." do
  51. url = GlobusJob.files_target_file_name "id321"
  52. expect( url ).to eq( "DeepBlueData_id321" )
  53. end
  54. end
  55. 1 describe "GlobusJob#globus_lock_file" do
  56. 1 it "returns the lock file name." do
  57. expect( GlobusJob.lock_file("id321" ) ).to eq(lock_file )
  58. end
  59. end
  60. 1 describe "GlobusJob#target_base_name" do
  61. 1 it "returns a target base name." do
  62. expect( GlobusJob.target_base_name( "id321" ) ).to eq( "DeepBlueData_id321" )
  63. end
  64. end
  65. 1 describe "GlobusJob#target_file_name" do
  66. 1 it "returns a target base name." do
  67. expect( GlobusJob.target_file_name( Pathname.new( 'aDir' ), "aFile" ) ).to eq( Pathname.new( 'aDir' ).join( 'aFile' ) )
  68. end
  69. end
  70. 1 describe "GlobusJob#target_file_name_env" do
  71. 1 let( :file ) { Pathname.new( 'aDir' ).join( '.test.atype.basename' ) }
  72. 1 it "returns a target base name." do
  73. expect( GlobusJob.target_file_name_env( Pathname.new( 'aDir' ), "atype", "basename" ) ).to eq( file )
  74. end
  75. end
  76. 1 describe "#globus_acquire_lock?" do
  77. 1 let( :job ) do
  78. j = described_class.new
  79. j.perform( "id321" )
  80. j
  81. end
  82. 1 context "when globus is locked" do
  83. 1 before do
  84. allow( job ).to receive( :globus_locked? ).and_return( true )
  85. end
  86. 1 it "returns false." do
  87. expect( job.send( :globus_acquire_lock? ) ).to eq( false )
  88. end
  89. end
  90. 1 context "when globus is not locked" do
  91. 1 before do
  92. allow( job ).to receive( :globus_locked? ).and_return( false )
  93. allow( job ).to receive( :globus_lock ).and_return( true )
  94. end
  95. 1 it "returns true." do
  96. expect( job.send( :globus_acquire_lock? ) ).to eq( true )
  97. end
  98. end
  99. end
  100. 1 describe "#globus_copy_job_complete?" do
  101. 1 let( :job ) do
  102. j = described_class.new
  103. j.perform( "abc" )
  104. j
  105. end
  106. 1 before do
  107. allow( Dir ).to receive( :exist? ).with( globus_target_download_dir ).and_return( true )
  108. end
  109. 1 it "returns true." do expect( job.send( :globus_copy_job_complete?, "id321" ) ).to eq( true ); end
  110. end
  111. 1 describe "#globus_error_file" do
  112. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  113. 1 it "returns the error file name." do
  114. expect( job.send( :globus_error_file ) ).to eq( error_file )
  115. end
  116. end
  117. 1 describe "#globus_error" do
  118. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  119. 1 let( :error_file_tmp ) { Tempfile.new( ".test.error.DeepBlueData_id321", globus_dir ) }
  120. 1 let( :error_msg ) { "An error message." }
  121. 1 before do
  122. allow( job ).to receive( :globus_error_file ).and_return( error_file_tmp.path )
  123. open( error_file_tmp.path, 'w' ) { |f| f << error_msg << "\n" }
  124. msg = "Globus: writing error message to #{error_file_tmp.path}"
  125. allow(Rails.logger).to receive(:debug) { :failure }
  126. allow( Rails.logger ).to receive( :debug ).with( msg )
  127. end
  128. 1 after do
  129. error_file_tmp.delete
  130. end
  131. 1 it "writes out the error" do
  132. expect( job.send( :globus_error, error_msg ) ).to eq( error_file_tmp.path )
  133. file_contents = nil
  134. open( error_file_tmp.path, 'r' ) { |f| file_contents = f.read.chomp! }
  135. expect( file_contents ).to eq( error_msg )
  136. end
  137. end
  138. 1 context "#globus_error_file_exists?" do
  139. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  140. 1 context "error file exists" do
  141. 1 before do
  142. allow( File ).to receive( :exist? ).with( error_file ).and_return( true )
  143. end
  144. 1 it "returns true if error file exists." do
  145. expect( job.send( :globus_error_file_exists? ) ).to eq( true )
  146. end
  147. end
  148. 1 context "error file exists and write to log flag is true" do
  149. 1 let( :job2 ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  150. 1 let( :error_file_tmp ) { Tempfile.new( ".test.error.DeepBlueData_id321", globus_dir ) }
  151. 1 let( :error_msg ) { "An error message." }
  152. 1 before do
  153. allow( job2 ).to receive( :globus_error_file ).and_return( error_file_tmp.path )
  154. allow( GlobusJob ).to receive( :error_file ).and_return( error_file_tmp.path )
  155. open( error_file_tmp.path, 'w' ) { |f| f << error_msg << "\n" }
  156. allow(Rails.logger).to receive(:debug) { :failure }
  157. allow( Rails.logger ).to receive( :debug ).with( "Globus: error file contains: #{error_msg}" )
  158. end
  159. 1 after do
  160. error_file_tmp.delete
  161. end
  162. 1 it "writes to the log when error file exists" do
  163. expect( job2.send( :globus_error_file_exists?, write_error_to_log: true ) ).to eq( true )
  164. end
  165. end
  166. 1 context "error file does not exist" do
  167. 1 before do
  168. allow( File ).to receive( :exist? ).with( error_file ).and_return( false )
  169. end
  170. 1 it "returns true if error file exists." do
  171. expect( job.send( :globus_error_file_exists? ) ).to eq( false )
  172. end
  173. end
  174. end
  175. 1 describe "#globus_error_reset" do
  176. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  177. 1 context "when error file exists." do
  178. 1 before do
  179. allow( File ).to receive( :exist? ).with( error_file ).and_return( true )
  180. allow( File ).to receive( :delete ).with( error_file )
  181. end
  182. 1 it "return true when file exists." do
  183. expect( job.send( :globus_error_reset ) ).to eq( true )
  184. end
  185. end
  186. 1 context "when error file doesn't exist." do
  187. 1 before do
  188. allow( File ).to receive( :exist? ).with( error_file ).and_return( false )
  189. end
  190. 1 it "return true when file doesn't exist." do
  191. expect( File ).not_to receive( :delete )
  192. expect( job.send( :globus_error_reset ) ).to eq( true )
  193. end
  194. end
  195. end
  196. 1 context "#globus_job_complete" do
  197. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  198. 1 let( :complete_file_tmp ) { Tempfile.new( ".test.complete.DeepBlueData_id321", globus_dir ) }
  199. 1 before do
  200. job.define_singleton_method( :globus_job_complete_file ) do "let the expect define the return value"; end
  201. allow( job ).to receive( :globus_job_complete_file ).and_return( complete_file_tmp.path )
  202. # log_msg = "Globus: job complete at #{timestamp}"
  203. allow( Rails.logger ).to receive( :debug )
  204. end
  205. 1 after do
  206. complete_file_tmp.delete
  207. end
  208. 1 it "writes out the globus complete file." do
  209. before = Time.now.round(0) - 1.second
  210. expect( job.send( :globus_job_perform_complete ) ).to eq(complete_file_tmp.path )
  211. after = Time.now.round(0) + 1.second
  212. file_contents = nil
  213. open( complete_file_tmp.path, 'r' ) { |f| file_contents = f.read.chomp! }
  214. between = Time.parse file_contents
  215. expect( between ).to be_between( before, after )
  216. end
  217. end
  218. 1 describe "#globus_job_perform" do
  219. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  220. 1 let( :globus_block ) { -> { job.inside_block } }
  221. 1 let( :lock_file_msg ) { "Globus: lock file #{lock_file}" }
  222. 1 before do
  223. job.define_singleton_method( :globus_job_complete? ) do true; end
  224. job.define_singleton_method( :inside_block ) do true; end
  225. end
  226. 1 context "when job complete" do
  227. 1 before do
  228. allow( job ).to receive( :globus_job_complete? ).and_return( true )
  229. allow(Rails.logger).to receive(:debug) { :failure }
  230. allow( Rails.logger ).to receive( :debug ).with( "Globus: skipping already complete globus job" )
  231. end
  232. 1 it "does not call globus block" do
  233. expect( GlobusJob.class_variable_get( :@@globus_enabled ) ).to eq( true )
  234. expect( job ).not_to receive( :globus_acquire_lock? )
  235. expect( job ).not_to receive( :inside_block )
  236. job.send( :globus_job_perform, concern_id: "id321", &globus_block )
  237. end
  238. end
  239. 1 context "when can't acquire lock" do
  240. 1 before do
  241. allow( job ).to receive( :globus_job_complete? ).and_return( false )
  242. allow( job ).to receive( :globus_acquire_lock? ).and_return( false )
  243. allow( job ).to receive( :globus_job_perform_in_progress )
  244. allow(Rails.logger).to receive(:debug) { :failure }
  245. allow( Rails.logger ).to receive( :debug ).with( lock_file_msg )
  246. end
  247. 1 it "does not call globus block." do
  248. expect( GlobusJob.class_variable_get( :@@globus_enabled ) ).to eq( true )
  249. expect( job ).not_to receive( :inside_block )
  250. job.send( :globus_job_perform, concern_id: "id321", &globus_block )
  251. end
  252. end
  253. 1 context "when can acquire lock" do
  254. 1 before do
  255. allow( job ).to receive( :globus_job_complete? ).and_return( false )
  256. allow( job ).to receive( :globus_acquire_lock? ).and_return( true )
  257. allow(Rails.logger).to receive(:debug) { :failure }
  258. allow( Rails.logger ).to receive( :debug ).with( lock_file_msg )
  259. allow( job ).to receive( :globus_error_reset )
  260. allow( job ).to receive( :globus_job_perform_complete_reset )
  261. allow( job ).to receive( :inside_block )
  262. allow( job ).to receive( :globus_job_perform_complete )
  263. allow( job ).to receive( :globus_unlock )
  264. end
  265. 1 it "calls globus block." do
  266. expect( GlobusJob.class_variable_get( :@@globus_enabled ) ).to eq( true )
  267. job.send( :globus_job_perform, concern_id: "id321", &globus_block )
  268. expect( job ).to have_received( :globus_unlock ).exactly( 2 ).times
  269. end
  270. end
  271. 1 context "when can acquire lock and error is thrown inside block," do
  272. 1 before do
  273. allow( job ).to receive( :globus_job_complete? ).and_return( false )
  274. allow( job ).to receive( :globus_acquire_lock? ).and_return( true )
  275. allow(Rails.logger).to receive(:debug) { :failure }
  276. allow( Rails.logger ).to receive( :debug ).with( lock_file_msg )
  277. allow( job ).to receive( :globus_error_reset )
  278. allow( job ).to receive( :globus_job_perform_complete_reset )
  279. allow( job ).to receive( :inside_block ).and_raise( StandardError, "generated error" )
  280. allow( Rails.logger ).to receive( :error )
  281. allow( job ).to receive( :globus_error ).with( /^Globus: StandardError: generated error at/ )
  282. allow( job ).to receive( :globus_unlock )
  283. end
  284. 1 it "calls globus block." do
  285. expect( GlobusJob.class_variable_get( :@@globus_enabled ) ).to eq( true )
  286. expect( job ).not_to receive( :globus_job_perform_complete )
  287. job.send( :globus_job_perform, concern_id: "id321", &globus_block )
  288. expect( Rails.logger ).to have_received( :error ).with( /^Globus: StandardError: generated error at/ )
  289. end
  290. end
  291. end
  292. 1 describe "#globus_job_complete_reset" do
  293. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  294. 1 let( :complete_file ) { "#{globus_dir}/prep/.test.complete.DeepBlueData_id321" }
  295. 1 context "when complete file exists." do
  296. 1 before do
  297. job.define_singleton_method( :globus_job_complete_file ) do "let the expect define the return value"; end
  298. allow( job ).to receive( :globus_job_complete_file ).and_return( complete_file )
  299. allow( File ).to receive( :exist? ).with( complete_file ).and_return( true )
  300. allow( File ).to receive( :delete ).with( complete_file )
  301. end
  302. 1 it "return true when file exists." do
  303. expect( job.send( :globus_job_perform_complete_reset ) ).to eq(true )
  304. end
  305. end
  306. 1 context "when complete file doesn't exist." do
  307. 1 before do
  308. job.define_singleton_method( :globus_job_complete_file ) do "let the expect define the return value"; end
  309. allow( job ).to receive( :globus_job_complete_file ).and_return( complete_file )
  310. allow( File ).to receive( :exist? ).with( complete_file ).and_return( false )
  311. end
  312. 1 it "return true when file doesn't exist." do
  313. expect( File ).not_to receive( :delete )
  314. expect( job.send( :globus_job_perform_complete_reset ) ).to eq(true )
  315. end
  316. end
  317. end
  318. 1 context "#globus_lock" do
  319. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  320. 1 let( :lock_file_tmp ) { Tempfile.new( ".test.lock.DeepBlueData_id321", globus_dir ) }
  321. 1 let( :current_token ) { GlobusJob.era_token }
  322. 1 before do
  323. allow( GlobusJob ).to receive( :lock_file ).and_return( lock_file_tmp.path )
  324. log_msg = "Globus: writing lock token #{current_token} to #{lock_file_tmp.path}"
  325. allow(Rails.logger).to receive(:debug) { :failure }
  326. allow( Rails.logger ).to receive( :debug ).with( log_msg )
  327. end
  328. 1 after do
  329. lock_file_tmp.delete
  330. end
  331. 1 it "creates a lock file with the current token in it." do
  332. expect( job.send( :globus_lock ) ).to eq( true )
  333. file_lock_token = nil
  334. open( lock_file_tmp.path, 'r' ) { |f| file_lock_token = f.read.chomp! }
  335. expect( file_lock_token ).to eq( current_token )
  336. end
  337. end
  338. 1 context "#globus_locked?" do
  339. 1 context "If error file exists" do
  340. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  341. 1 before do
  342. allow( GlobusJob ).to receive( :error_file_exists? ).and_return( true )
  343. end
  344. 1 it "then return false if error file exists." do
  345. expect( job.send( :globus_locked? ) ).to eq( false )
  346. end
  347. end
  348. 1 context "If lock file does not exist" do
  349. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  350. 1 before do
  351. allow( GlobusJob ).to receive( :error_file_exists? ).and_return( false )
  352. allow( File ).to receive( :exist? ).with( lock_file ).and_return( false )
  353. end
  354. 1 it "then return false." do
  355. expect( job.send( :globus_locked? ) ).to eq( false )
  356. end
  357. end
  358. 1 context "lock file exists with different token." do
  359. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  360. 1 let( :lock_file_tmp ) { Tempfile.new( ".test.lock.DeepBlueData_id321", globus_dir ) }
  361. 1 let( :current_token ) { GlobusJob.era_token }
  362. 1 let( :lock_token ) { "theToken" }
  363. 1 before do
  364. allow( GlobusJob ).to receive( :error_file_exists? ).and_return( false )
  365. allow( GlobusJob ).to receive( :lock_file ).and_return( lock_file_tmp.path )
  366. open( lock_file_tmp.path, 'w' ) { |f| f << lock_token << "\n" }
  367. log_msg = "Globus: testing token from #{lock_file_tmp.path}: current_token: #{current_token} == lock_token: #{lock_token}: false"
  368. allow(Rails.logger).to receive(:debug) { :failure }
  369. allow( Rails.logger ).to receive( :debug ).with( log_msg )
  370. end
  371. 1 after do
  372. lock_file_tmp.delete
  373. end
  374. 1 it "then returns false when tokens are not equal." do
  375. expect( job.send( :globus_locked? ) ).to eq( false )
  376. end
  377. end
  378. 1 context "lock file exists with same token." do
  379. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  380. 1 let( :lock_file_tmp ) { Tempfile.new( ".test.lock.DeepBlueData_id321", globus_dir ) }
  381. 1 let( :current_token ) { GlobusJob.era_token }
  382. 1 let( :lock_token ) { GlobusJob.era_token }
  383. 1 before do
  384. allow( GlobusJob ).to receive( :error_file_exists? ).and_return( false )
  385. allow( GlobusJob ).to receive( :lock_file ).and_return(lock_file_tmp.path )
  386. open( lock_file_tmp.path, 'w' ) { |f| f << lock_token << "\n" }
  387. log_msg = "Globus: testing token from #{lock_file_tmp.path}: current_token: #{current_token} == lock_token: #{lock_token}: true"
  388. allow(Rails.logger).to receive(:debug) { :failure }
  389. allow( Rails.logger ).to receive( :debug ).with( log_msg )
  390. end
  391. 1 after do
  392. lock_file_tmp.delete
  393. end
  394. 1 it "then returns true when tokens are equal." do
  395. expect( job.send( :globus_locked? ) ).to eq( true )
  396. end
  397. end
  398. end
  399. 1 context "#globus_unlock" do
  400. 1 context "when globus lock file is nil" do
  401. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  402. 1 before do
  403. job.define_singleton_method( :set_globus_lock_file_nil ) do @globus_lock_file = nil; end
  404. job.set_globus_lock_file_nil
  405. end
  406. 1 it "then return nil" do
  407. expect( job.send( :globus_unlock ) ).to eq( nil )
  408. end
  409. end
  410. 1 context "when globus lock file does not exist" do
  411. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  412. 1 before do
  413. allow( File ).to receive( :exist? ).with( lock_file ).and_return( false )
  414. end
  415. 1 it "then return nil" do
  416. expect( File ).not_to receive( :delete )
  417. expect( job.send( :globus_unlock ) ).to eq( nil )
  418. end
  419. end
  420. 1 context "when globus lock file exists" do
  421. 1 let( :job ) { j = described_class.new; j.perform( "id321" ); j } # rubocop:disable Style/Semicolon
  422. 1 before do
  423. allow( File ).to receive( :exist? ).with( lock_file ).and_return( true )
  424. allow( File ).to receive( :delete ).with( lock_file )
  425. log_msg = "Globus: unlock by deleting file #{lock_file}"
  426. allow(Rails.logger).to receive(:debug) { :failure }
  427. allow( Rails.logger ).to receive( :debug ).with( log_msg )
  428. end
  429. 1 it "then return nil" do
  430. expect( job.send( :globus_unlock ) ).to eq( nil )
  431. end
  432. end
  433. end
  434. 1 context "#target_dir_name" do
  435. 1 let( :job ) { described_class.new }
  436. 1 let( :dir ) { Pathname.new( 'aDir' ).join( 'aSubdir' ) }
  437. 1 context "don't create dir." do
  438. 1 it "returns a target base name." do
  439. expect( job.send(:target_dir_name2, Pathname.new('aDir' ), "aSubdir" ) ).to eq(dir )
  440. end
  441. end
  442. 1 context "create dir if it doesn't exist." do
  443. 1 before do
  444. allow( Dir ).to receive( :exist? ).with( dir ).and_return( false )
  445. allow( Dir ).to receive( :mkdir ).with( dir )
  446. end
  447. 1 it "returns a target base name and creates the dir." do
  448. expect( job.send(:target_dir_name2, Pathname.new('aDir' ), "aSubdir", mkdir: true ) ).to eq(dir )
  449. end
  450. end
  451. 1 context "don't create dir if it exists." do
  452. 1 before do
  453. allow( Dir ).to receive( :exist? ).with( dir ).and_return( true )
  454. end
  455. 1 it "returns a target base name and doesn't create the dir." do
  456. expect( job.send(:target_dir_name2, Pathname.new('aDir' ), "aSubdir", mkdir: false ) ).to eq(dir )
  457. end
  458. end
  459. end
  460. 1 describe "#target_download_dir" do
  461. 1 let( :job ) { described_class.new }
  462. 1 it "returns target dowload dir name." do
  463. expect( job.send(:target_download_dir2, "id321" ) ).to eq(globus_target_download_dir )
  464. end
  465. end
  466. 1 context "#target_prep_dir" do
  467. 1 let( :job ) { described_class.new }
  468. 1 let( :prefix ) { GlobusJob.server_prefix(str: '_') }
  469. 1 let( :dir ) { globus_prep_dir.join "#{prefix}DeepBlueData_id321" }
  470. 1 context "don't create prep dir." do
  471. 1 it "returns a prep dir name." do
  472. expect( job.send(:target_prep_dir2, "id321", prefix: prefix ) ).to eq(dir )
  473. end
  474. end
  475. 1 context "create prep dir if it doesn't exist." do
  476. 1 before do
  477. allow( Dir ).to receive( :exist? ).with( dir ).and_return( false )
  478. allow( Dir ).to receive( :mkdir ).with( dir )
  479. end
  480. 1 it "returns prep dir name and creates the dir." do
  481. expect( job.send(:target_prep_dir2, "id321", prefix: prefix, mkdir: true ) ).to eq(dir )
  482. end
  483. end
  484. 1 context "don't create prep dir if it exists." do
  485. 1 it "returns prep dir name name and doesn't create the dir." do
  486. expect( job.send(:target_prep_dir2, "id321", prefix: prefix, mkdir: false ) ).to eq(dir )
  487. end
  488. end
  489. end
  490. 1 context "#target_prep_dir_tmp" do
  491. 1 let( :job ) { described_class.new }
  492. 1 let( :prefix ) { GlobusJob.server_prefix(str: '_') }
  493. 1 let( :dir ) { globus_prep_dir.join "#{prefix}DeepBlueData_id321_tmp" }
  494. 1 context "don't create tmp prep dir." do
  495. 1 it "returns tmp prep dir name." do
  496. expect( job.send(:target_prep_tmp_dir2, "id321", prefix: prefix ) ).to eq(dir )
  497. end
  498. end
  499. 1 context "create tmp prep dir if it doesn't exist." do
  500. 1 before do
  501. allow( Dir ).to receive( :exist? ).with( dir ).and_return( false )
  502. allow( Dir ).to receive( :mkdir ).with( dir )
  503. end
  504. 1 it "returns tmp prep dir name and creates the dir." do
  505. expect( job.send(:target_prep_tmp_dir2, "id321", prefix: prefix, mkdir: true ) ).to eq(dir )
  506. end
  507. end
  508. 1 context "don't create tmp prep dir if it exists." do
  509. 1 it "returns tmp prep dir name name and doesn't create the dir." do
  510. expect( job.send(:target_prep_tmp_dir2, "id321", prefix: prefix, mkdir: false ) ).to eq(dir )
  511. end
  512. end
  513. end
  514. end

spec/jobs/globus_restart_all_job_spec.rb

95.0% lines covered

100 relevant lines. 95 lines covered and 5 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'rails_helper'
  3. # require 'uri'
  4. 1 RSpec.configure do |config|
  5. 1 config.filter_run_excluding globus_enabled: :true unless DeepBlueDocs::Application.config.globus_enabled
  6. end
  7. 1 describe GlobusRestartAllJob, "GlobusJob globus_enabled: :true", globus_enabled: :true do # rubocop:disable RSpec/DescribeMethod
  8. 6 let( :globus_dir ) { Pathname "/tmp/deepbluedata-globus" }
  9. 6 let( :target_name ) { "DataCORE_Restart_All" }
  10. # let( :target_name_prep_dir ) { "#{GlobusJob.server_prefix(str:'_')}#{target_name}" }
  11. 6 let( :globus_prep_dir ) { globus_dir.join 'prep' }
  12. 6 let( :job_complete_file ) { globus_prep_dir.join ".test.restarted.#{target_name}" }
  13. 2 let( :error_file ) { globus_prep_dir.join ".test.error.#{target_name}" }
  14. 2 let( :lock_file ) { globus_prep_dir.join ".test.lock.#{target_name}" }
  15. 1 describe "#perform" do
  16. 1 context "when can acquire lock" do
  17. 1 let( :job ) do
  18. j = GlobusCopyJob.new
  19. j.define_singleton_method( :set_id, id ) do |id|
  20. @globus_concern_id = id
  21. self
  22. end
  23. j
  24. end
  25. 2 let( :log_prefix ) { "Globus: globus_restart_all_job " }
  26. 2 let( :globus_era_file ) { GlobusJob.era_token }
  27. 2 let( :target ) { "DataCORE_" }
  28. 2 let( :id00 ) { "id000" }
  29. 2 let( :file00 ) { "#{globus_prep_dir}/.development.lock.#{target}#{id00}" }
  30. 2 let( :dir00 ) { "#{globus_prep_dir}/development_#{target}#{id00}" }
  31. 2 let( :dir00tmp ) { "#{dir00}_tmp" }
  32. 2 let( :id01 ) { "id001" }
  33. 2 let( :file01 ) { "#{globus_prep_dir}/.test.lock.#{target}#{id01}" }
  34. 2 let( :dir01 ) { "#{globus_prep_dir}/test_#{target}#{id01}" }
  35. 2 let( :dir01tmp ) { "#{dir01}_tmp" }
  36. 2 let( :id02 ) { "id002" }
  37. 2 let( :file02 ) { "#{globus_prep_dir}/.test.error.#{target}#{id02}" }
  38. 1 let( :files ) do
  39. 1 [ globus_era_file,
  40. file00,
  41. dir00,
  42. dir00tmp,
  43. file01,
  44. dir01,
  45. dir01tmp,
  46. file02,
  47. file03,
  48. dir04,
  49. dir05tmp ].map( &:to_s )
  50. end
  51. 2 let( :id03 ) { "id003" }
  52. 2 let( :file03 ) { "#{globus_prep_dir}/.test.lock.#{target}#{id03}" }
  53. 2 let( :id04 ) { "id004" }
  54. 2 let( :dir04 ) { "#{globus_prep_dir}/test_#{target}#{id04}" }
  55. 2 let( :id05 ) { "id005" }
  56. 2 let( :dir05tmp ) { "#{globus_prep_dir}/test_#{target}#{id05}_tmp" }
  57. 1 before do
  58. 1 File.delete lock_file if File.exist? lock_file
  59. 1 File.delete error_file if File.exist? error_file
  60. 1 File.delete job_complete_file if File.exist? job_complete_file
  61. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  62. 1 allow( Dir ).to receive( :glob ).with( any_args ).and_return( files )
  63. 1 allow( GlobusCopyJob ).to receive( :perform_later ).with( any_args )
  64. end
  65. 1 it "calls globus block." do
  66. 1 described_class.perform_now
  67. # expect( Rails.logger ).to have_received( :debug ).with( 'bogus so we can look at the logger output' )
  68. 1 expect( GlobusCopyJob ).to have_received( :perform_later ).with( id01 )
  69. 1 expect( GlobusCopyJob ).to have_received( :perform_later ).with( id02 )
  70. 1 expect( GlobusCopyJob ).to have_received( :perform_later ).with( id03 )
  71. 1 expect( GlobusCopyJob ).to have_received( :perform_later ).with( id04 )
  72. 1 expect( GlobusCopyJob ).to have_received( :perform_later ).with( id05 )
  73. 1 expect( GlobusCopyJob ).to have_received( :perform_later ).exactly( 5 ).times
  74. 1 expect( Rails.logger ).to have_received( :debug ).with( "#{log_prefix}restart all complete" )
  75. # expect( Rails.logger ).to have_received( :debug ).with( 'bogus so we can look at the logger output' )
  76. # expect( Rails.logger ).not_to have_received( :error )
  77. 1 expect( File.exist?( job_complete_file ) ).to eq( true )
  78. 1 expect( File.exist?( error_file ) ).to eq( false )
  79. 1 expect( File.exist?( lock_file ) ).to eq( false )
  80. end
  81. 1 after do
  82. 1 File.delete job_complete_file if File.exist? job_complete_file
  83. end
  84. end
  85. end
  86. 1 describe "#globus_job_complete_file" do
  87. 2 let( :job ) { described_class.new }
  88. 1 before do
  89. 2 job.define_singleton_method( :set_parms ) do @globus_concern_id = "Restart_All"; end
  90. 1 job.set_parms
  91. end
  92. 1 it "returns the ready file name." do
  93. 1 expect( job.send( :globus_job_complete_file ) ).to eq( job_complete_file )
  94. end
  95. end
  96. 1 describe "#globus_job_complete?" do
  97. 4 let( :job ) { described_class.new }
  98. 4 let( :job_complete_msg ) { " globus job complete file #{job_complete_file}" }
  99. 3 let( :time_now ) { Time.now }
  100. 2 let( :time_before_now ) { time_now - 9.seconds }
  101. 1 before do
  102. 6 job.define_singleton_method( :set_parms ) do @globus_concern_id = "Restart_All"; end
  103. 3 job.set_parms
  104. end
  105. 1 context "when file does not exist" do
  106. 1 before do
  107. 1 allow( Rails.logger ).to receive( :debug )
  108. 1 allow( File ).to receive( :exist? ).with( job_complete_file ).and_return( false )
  109. end
  110. 1 it "return true." do
  111. 1 expect( job.send( :globus_job_complete? ) ).to eq( false )
  112. 1 expect( Rails.logger ).to have_received( :debug ).with( job_complete_msg )
  113. end
  114. end
  115. 1 context "when file exists and time matches" do
  116. 1 before do
  117. 1 allow( Rails.logger ).to receive( :debug )
  118. 1 allow( File ).to receive( :exist? ).with( job_complete_file ).and_return( true )
  119. # allow( File ).to receive( :birthtime ).with( job_complete_file ).and_return( time_now )
  120. 1 allow( job ).to receive( :last_complete_time ).with( job_complete_file ).and_return( time_now )
  121. 1 allow( GlobusJob ).to receive( :era_token_time ).with( no_args ).and_return( time_now )
  122. end
  123. 1 it "return true." do
  124. 1 expect( job.send( :globus_job_complete? ) ).to eq( true )
  125. 1 expect( Rails.logger ).to have_received( :debug ).with( job_complete_msg )
  126. # expect( Rails.logger ).to have_received( :debug ).with( 'bogus' )
  127. end
  128. end
  129. 1 context "when file exists and time does not match" do
  130. 1 before do
  131. 1 allow( Rails.logger ).to receive( :debug )
  132. 1 allow( File ).to receive( :exist? ).with( job_complete_file ).and_return( true )
  133. # allow( File ).to receive( :birthtime ).with( job_complete_file ).and_return( time_before_now )
  134. 1 allow( job ).to receive( :last_complete_time ).with( job_complete_file ).and_return( time_before_now )
  135. 1 allow( GlobusJob ).to receive( :era_token_time ).with( no_args ).and_return( time_now )
  136. end
  137. 1 it "return false." do
  138. 1 expect( job.send( :globus_job_complete? ) ).to eq( false )
  139. 1 expect( Rails.logger ).to have_received( :debug ).with( job_complete_msg )
  140. # expect( Rails.logger ).to have_received( :debug ).with( 'bogus' )
  141. end
  142. end
  143. end
  144. end

spec/mailers/deepblue_mailer_spec.rb

100.0% lines covered

8 relevant lines. 8 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe DeepblueMailer do
  3. 1 describe '#send_an_email' do
  4. 1 before {
  5. 1 allow(subject).to receive(:mail).with(to: "to", from: "from", subject: "subject", body: "body")
  6. }
  7. 1 it "calls email function" do
  8. 1 expect(subject).to receive(:mail).with(to: "to", from: "from", subject: "subject", body: "body")
  9. 1 subject.send_an_email to: "to", from: "from", subject: "subject", body: "body"
  10. end
  11. end
  12. end

spec/models/ability_spec.rb

88.0% lines covered

25 relevant lines. 22 lines covered and 3 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe Ability do
  3. 2 let(:user) { FactoryBot.create :user }
  4. 3 let(:options) { {} }
  5. 3 let(:ability) { described_class.new(user, options) }
  6. 1 describe '#can_deposit?' do
  7. 1 context 'when neither an admin nor depositor' do
  8. 1 it 'returns false' do
  9. 1 expect(ability.admin?).to be false
  10. 1 expect(ability.depositor?).to be false
  11. 1 expect(ability.can? :create, DataSet).to be false
  12. end
  13. end
  14. 1 context 'when a depositor' do
  15. 2 let(:admin_set) { AdminSet.find(AdminSet.find_or_create_default_admin_set_id) }
  16. 1 before do
  17. # creates permission template and depositor permissions
  18. 1 Hyrax::AdminSetCreateService.new(admin_set: admin_set, creating_user: user).create
  19. end
  20. 1 it 'returns true' do
  21. expect(ability.admin?).to be false
  22. expect(ability.depositor?).to be true
  23. expect(ability.can? :create, DataSet).to be true
  24. end
  25. end
  26. 1 context 'when an admin' do
  27. 2 let(:user) { FactoryBot.create :admin }
  28. 1 it 'returns true' do
  29. 1 expect(ability.admin?).to be true
  30. 1 expect(ability.depositor?).to be false
  31. 1 expect(ability.can? :create, DataSet).to be true
  32. end
  33. end
  34. end
  35. end

spec/models/collection_spec.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe Collection do
  3. 1 it "has tests" do
  4. 1 skip "Add your tests here"
  5. end
  6. end

spec/models/concerns/deepblue/abstract_event_behavior_spec.rb

100.0% lines covered

88 relevant lines. 88 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 class CurationConcernMock
  3. 1 include ::Deepblue::AbstractEventBehavior
  4. end
  5. 1 RSpec.describe Deepblue::AbstractEventBehavior do
  6. 9 let( :event ) { 'the_event' }
  7. 9 let( :id ) { 'id1234' }
  8. 5 let( :behavior ) { 'some_behavior' }
  9. 3 let( :key ) { "#{id}.#{event}" }
  10. 5 let( :key_with_behavior ) { "#{id}.#{event}.#{behavior}" }
  11. 5 let( :cache_value ) { 'the cache value ' }
  12. 1 describe 'constants' do
  13. 1 it do
  14. 1 expect( Deepblue::AbstractEventBehavior::EVENT_CHARACTERIZE ).to eq 'characterize'
  15. 1 expect( Deepblue::AbstractEventBehavior::EVENT_CHILD_ADD ).to eq 'child_add'
  16. 1 expect( Deepblue::AbstractEventBehavior::EVENT_CHILD_REMOVE ).to eq 'child_remove'
  17. 1 expect( Deepblue::AbstractEventBehavior::EVENT_CREATE ).to eq 'create'
  18. 1 expect( Deepblue::AbstractEventBehavior::EVENT_CREATE_DERIVATIVE ).to eq 'create_derivative'
  19. 1 expect( Deepblue::AbstractEventBehavior::EVENT_DESTROY ).to eq 'destroy'
  20. 1 expect( Deepblue::AbstractEventBehavior::EVENT_DOWNLOAD ).to eq 'download'
  21. 1 expect( Deepblue::AbstractEventBehavior::EVENT_EMBARGO ).to eq 'embargo'
  22. 1 expect( Deepblue::AbstractEventBehavior::EVENT_FIXITY_CHECK ).to eq 'fixity_check'
  23. 1 expect( Deepblue::AbstractEventBehavior::EVENT_GLOBUS ).to eq 'globus'
  24. 1 expect( Deepblue::AbstractEventBehavior::EVENT_INGEST ).to eq 'ingest'
  25. 1 expect( Deepblue::AbstractEventBehavior::EVENT_MIGRATE ).to eq 'migrate'
  26. 1 expect( Deepblue::AbstractEventBehavior::EVENT_MINT_DOI ).to eq 'mint_doi'
  27. 1 expect( Deepblue::AbstractEventBehavior::EVENT_PUBLISH ).to eq 'publish'
  28. 1 expect( Deepblue::AbstractEventBehavior::EVENT_TOMBSTONE ).to eq 'tombstone'
  29. 1 expect( Deepblue::AbstractEventBehavior::EVENT_UNEMBARGO ).to eq 'unembargo'
  30. 1 expect( Deepblue::AbstractEventBehavior::EVENT_UNPUBLISH ).to eq 'unpublish'
  31. 1 expect( Deepblue::AbstractEventBehavior::EVENT_UPDATE ).to eq 'update'
  32. 1 expect( Deepblue::AbstractEventBehavior::EVENT_UPDATE_AFTER ).to eq 'update_after'
  33. 1 expect( Deepblue::AbstractEventBehavior::EVENT_UPDATE_BEFORE ).to eq 'update_before'
  34. 1 expect( Deepblue::AbstractEventBehavior::EVENT_UPDATE_VERSION ).to eq 'update_version'
  35. 1 expect( Deepblue::AbstractEventBehavior::EVENT_UPLOAD ).to eq 'upload'
  36. 1 expect( Deepblue::AbstractEventBehavior::EVENT_VIRUS_SCAN ).to eq 'virus_scan'
  37. 1 expect( Deepblue::AbstractEventBehavior::EVENT_WORKFLOW ).to eq 'workflow'
  38. 1 expect( Deepblue::AbstractEventBehavior::EVENTS ).to eq [
  39. Deepblue::AbstractEventBehavior::EVENT_CHARACTERIZE,
  40. Deepblue::AbstractEventBehavior::EVENT_CHILD_ADD,
  41. Deepblue::AbstractEventBehavior::EVENT_CHILD_REMOVE,
  42. Deepblue::AbstractEventBehavior::EVENT_CREATE,
  43. Deepblue::AbstractEventBehavior::EVENT_CREATE_DERIVATIVE,
  44. Deepblue::AbstractEventBehavior::EVENT_DESTROY,
  45. Deepblue::AbstractEventBehavior::EVENT_DOWNLOAD,
  46. Deepblue::AbstractEventBehavior::EVENT_EMBARGO,
  47. Deepblue::AbstractEventBehavior::EVENT_FIXITY_CHECK,
  48. Deepblue::AbstractEventBehavior::EVENT_GLOBUS,
  49. Deepblue::AbstractEventBehavior::EVENT_INGEST,
  50. Deepblue::AbstractEventBehavior::EVENT_MIGRATE,
  51. Deepblue::AbstractEventBehavior::EVENT_MINT_DOI,
  52. Deepblue::AbstractEventBehavior::EVENT_PUBLISH,
  53. Deepblue::AbstractEventBehavior::EVENT_TOMBSTONE,
  54. Deepblue::AbstractEventBehavior::EVENT_UNEMBARGO,
  55. Deepblue::AbstractEventBehavior::EVENT_UNPUBLISH,
  56. Deepblue::AbstractEventBehavior::EVENT_UPDATE,
  57. Deepblue::AbstractEventBehavior::EVENT_UPDATE_AFTER,
  58. Deepblue::AbstractEventBehavior::EVENT_UPDATE_BEFORE,
  59. Deepblue::AbstractEventBehavior::EVENT_UPDATE_VERSION,
  60. Deepblue::AbstractEventBehavior::EVENT_UPLOAD,
  61. Deepblue::AbstractEventBehavior::EVENT_VIRUS_SCAN,
  62. Deepblue::AbstractEventBehavior::EVENT_WORKFLOW
  63. ]
  64. 1 expect( Deepblue::AbstractEventBehavior::IGNORE_BLANK_KEY_VALUES ).to eq true
  65. 1 expect( Deepblue::AbstractEventBehavior::USE_BLANK_KEY_VALUES ).to eq false
  66. end
  67. end
  68. 1 describe '.event_attributes_cache_exist?' do
  69. 3 subject { CurationConcernMock.new }
  70. 1 context 'with behavior' do
  71. 1 before do
  72. 1 allow( Rails.cache ).to receive( :exist? ).with( key_with_behavior ).and_return true
  73. end
  74. 1 it do
  75. 1 expect( subject.event_attributes_cache_exist?( event: event, id: id, behavior: behavior ) ).to eq true
  76. end
  77. end
  78. 1 context 'without behavior' do
  79. 1 before do
  80. 1 allow( Rails.cache ).to receive( :exist? ).with( key ).and_return true
  81. end
  82. 1 it do
  83. 1 expect( subject.event_attributes_cache_exist?( event: event, id: id ) ).to eq true
  84. end
  85. end
  86. end
  87. 1 describe '.event_attributes_cache_fetch' do
  88. 3 subject { CurationConcernMock.new }
  89. 1 context 'with behavior' do
  90. 1 before do
  91. 1 allow( Rails.cache ).to receive( :fetch ).with( key_with_behavior ).and_return cache_value
  92. end
  93. 1 it do
  94. 1 expect( subject.event_attributes_cache_fetch( event: event, id: id, behavior: behavior ) ).to eq cache_value
  95. end
  96. end
  97. 1 context 'without behavior' do
  98. 2 let( :key ) { "#{id}.#{event}" }
  99. 1 before do
  100. 1 allow( Rails.cache ).to receive( :fetch ).with( key ).and_return cache_value
  101. end
  102. 1 it do
  103. 1 expect( subject.event_attributes_cache_fetch( event: event, id: id ) ).to eq cache_value
  104. end
  105. end
  106. end
  107. 1 describe '.event_attributes_cache_key' do
  108. 3 subject { CurationConcernMock.new }
  109. 1 context 'with behavior' do
  110. 2 let( :result ) { key_with_behavior }
  111. 1 it do
  112. 1 expect( subject.event_attributes_cache_key( event: event, id: id, behavior: behavior ) ).to eq result
  113. end
  114. end
  115. 1 context 'without behavior' do
  116. 2 let( :result ) { key }
  117. 1 it do
  118. 1 expect( subject.event_attributes_cache_key( event: event, id: id, behavior: nil ) ).to eq result
  119. 1 expect( subject.event_attributes_cache_key( event: event, id: id, behavior: '' ) ).to eq result
  120. 1 expect( subject.event_attributes_cache_key( event: event, id: id ) ).to eq result
  121. end
  122. end
  123. end
  124. 1 describe '.event_attributes_cache_write' do
  125. 3 subject { CurationConcernMock.new }
  126. 1 context 'with behavior' do
  127. 1 before do
  128. 1 allow( Rails.cache ).to receive( :write ).with( key_with_behavior, cache_value )
  129. end
  130. 1 it do
  131. 1 subject.event_attributes_cache_write( event: event, id: id, attributes: cache_value, behavior: behavior )
  132. end
  133. end
  134. 1 context 'without behavior' do
  135. 2 let( :key ) { "#{id}.#{event}" }
  136. 1 before do
  137. 1 allow( Rails.cache ).to receive( :write ).with( key, cache_value )
  138. end
  139. 1 it do
  140. 1 subject.event_attributes_cache_write( event: event, id: id, attributes: cache_value )
  141. end
  142. end
  143. end
  144. end

spec/models/concerns/deepblue/metadata_behavior_spec.rb

97.4% lines covered

77 relevant lines. 75 lines covered and 2 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require_relative '../../../../app/models/concerns/deepblue/abstract_event_behavior'
  3. 1 require_relative '../../../../app/models/concerns/deepblue/metadata_behavior'
  4. 1 class CurationConcernEmptyMock
  5. 1 include ::Deepblue::MetadataBehavior
  6. end
  7. 1 class CurationConcernMock
  8. 1 include ::Deepblue::MetadataBehavior
  9. 1 def description
  10. 4 ['The Description']
  11. end
  12. 1 def id
  13. 10 'id123'
  14. end
  15. 1 def title
  16. 8 ['The Title', 'Part 2']
  17. end
  18. 1 def visiblity
  19. Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
  20. end
  21. 1 def metadata_keys_all
  22. 2 %i[ id title description ]
  23. end
  24. 1 def metadata_keys_brief
  25. 2 %i[ id title ]
  26. end
  27. 1 def metadata_hash_override( key:, ignore_blank_values:, key_values: )
  28. 10 value = nil
  29. 10 handled = case key.to_s
  30. when 'description'
  31. 2 value = description
  32. 2 true
  33. else
  34. 8 false
  35. end
  36. 10 return false unless handled
  37. 2 if ignore_blank_values
  38. key_values[key] = value if value.present?
  39. else
  40. 2 key_values[key] = value
  41. end
  42. 2 return true
  43. end
  44. end
  45. 1 RSpec.describe Deepblue::AbstractEventBehavior do
  46. 2 let( :empty_mock ) { CurationConcernEmptyMock.new }
  47. 5 let( :mock ) { CurationConcernMock.new }
  48. 1 describe 'constants' do
  49. 1 it do
  50. 1 expect( Deepblue::MetadataBehavior::METADATA_FIELD_SEP ).to eq '; '
  51. 1 expect( Deepblue::MetadataBehavior::METADATA_REPORT_DEFAULT_DEPTH ).to eq 2
  52. 1 expect( Deepblue::MetadataBehavior::METADATA_REPORT_DEFAULT_FILENAME_POST ).to eq '_metadata_report'
  53. 1 expect( Deepblue::MetadataBehavior::METADATA_REPORT_DEFAULT_FILENAME_EXT ).to eq '.txt'
  54. end
  55. end
  56. 1 describe 'default values' do
  57. 1 it do
  58. 1 expect( empty_mock.metadata_keys_all ).to eq []
  59. 1 expect( empty_mock.metadata_keys_brief ).to eq []
  60. 1 expect( empty_mock.metadata_hash_override( key: 'key', ignore_blank_values: false, key_values: [ key: 'value' ] ) ).to eq false
  61. 1 expect( empty_mock.metadata_report_label_override(metadata_key: 'key', metadata_value: 'value' ) ).to eq nil
  62. 1 ignore_blank_key_values, keys = empty_mock.metadata_report_keys
  63. 1 expect( ignore_blank_key_values ).to eq ::Deepblue::AbstractEventBehavior::IGNORE_BLANK_KEY_VALUES
  64. 1 expect( keys ).to eq []
  65. 1 expect( empty_mock.metadata_report_contained_objects ).to eq []
  66. 1 expect( empty_mock.metadata_report_title_pre ).to eq ''
  67. 1 expect( empty_mock.metadata_report_title_field_sep ).to eq ' '
  68. end
  69. end
  70. 1 describe 'metadata_hash' do
  71. 2 let( :empty_hash ) { {} }
  72. 2 let( :expected_hash_all ) { { id: mock.id, title: mock.title, description: mock.description } }
  73. 2 let( :expected_hash_brief ) { { id: mock.id, title: mock.title } }
  74. 2 let( :expected_kv_hash_all ) { { key: 'value', id: mock.id, title: mock.title, description: mock.description } }
  75. 2 let( :expected_kv_hash_brief ) { { key: 'value', id: mock.id, title: mock.title } }
  76. 1 context 'empty' do
  77. 1 it do
  78. 1 expect( mock.metadata_hash( metadata_keys: [], ignore_blank_values: false ) ).to eq empty_hash
  79. 1 expect( mock.metadata_hash( metadata_keys: [], ignore_blank_values: false, **empty_hash ) ).to eq empty_hash
  80. end
  81. end
  82. 1 context 'returns correct value for id, title' do
  83. 1 it do
  84. 1 expect( mock.metadata_hash( metadata_keys: mock.metadata_keys_brief, ignore_blank_values: false ) ).to eq expected_hash_brief
  85. 1 expect( mock.metadata_hash( metadata_keys: mock.metadata_keys_all, ignore_blank_values: false ) ).to eq expected_hash_all
  86. 1 kv_hash = { key: 'value' }
  87. 1 expect( mock.metadata_hash( metadata_keys: mock.metadata_keys_brief, ignore_blank_values: false, **kv_hash ) ).to eq expected_kv_hash_brief
  88. 1 kv_hash = { key: 'value' }
  89. 1 expect( mock.metadata_hash( metadata_keys: mock.metadata_keys_all, ignore_blank_values: false, **kv_hash ) ).to eq expected_kv_hash_all
  90. end
  91. end
  92. end
  93. 1 describe 'metadata_report_filename' do
  94. 3 let( :pathname_dir ) { "/some/path" }
  95. 3 let( :filename_pre ) { "pre_" }
  96. 1 context 'basic parms' do
  97. 1 it do
  98. 1 expect( mock.metadata_report_filename( pathname_dir: Pathname.new( pathname_dir ),
  99. filename_pre: filename_pre ) ).to eq Pathname.new "/some/path/pre_id123_metadata_report.txt"
  100. end
  101. end
  102. 1 context 'all parms' do
  103. 1 it do
  104. 1 expect( mock.metadata_report_filename( pathname_dir: Pathname.new( pathname_dir ),
  105. filename_pre: filename_pre,
  106. filename_post: "_post",
  107. filename_ext: ".ext" ) ).to eq Pathname.new "/some/path/pre_id123_post.ext"
  108. end
  109. end
  110. end
  111. end

spec/models/data_set_spec.rb

95.86% lines covered

338 relevant lines. 324 lines covered and 14 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'rails_helper'
  3. 1 RSpec.describe DataSet do
  4. 23 let( :authoremail ) { 'authoremail@umich.edu' }
  5. 23 let( :creator ) { 'Creator, A' }
  6. 6 let( :current_user ) { 'user@umich.edu' }
  7. 23 let( :date_created ) { '2018-02-28' }
  8. 17 let( :depositor ) { authoremail }
  9. 23 let( :description ) { 'The Description' }
  10. 23 let( :id ) { '0123458678' }
  11. 17 let( :methodology ) { 'The Methodology' }
  12. 21 let( :rights_license ) { 'The Rights License' }
  13. 23 let( :title ) { 'The Title' }
  14. 3 let( :visibility_private ) { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE }
  15. 12 let( :visibility_public ) { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC }
  16. 1 let( :metadata_keys_all ) {
  17. 4 %i[
  18. access_deepblue
  19. admin_set_id
  20. authoremail
  21. creator
  22. curation_notes_admin
  23. curation_notes_user
  24. date_coverage
  25. date_created
  26. date_modified
  27. date_published
  28. date_updated
  29. depositor
  30. description
  31. doi
  32. file_set_ids
  33. fundedby
  34. fundedby_other
  35. grantnumber
  36. keyword
  37. language
  38. location
  39. methodology
  40. prior_identifier
  41. referenced_by
  42. rights_license
  43. rights_license_other
  44. subject_discipline
  45. title
  46. tombstone
  47. total_file_count
  48. total_file_size
  49. total_file_size_human_readable
  50. visibility
  51. ]
  52. }
  53. 1 let( :metadata_keys_brief ) {
  54. 1 %i[
  55. authoremail
  56. title
  57. visibility
  58. ]
  59. }
  60. 1 let( :metadata_keys_update ) {
  61. 2 %i[
  62. authoremail
  63. title
  64. visibility
  65. ]
  66. }
  67. 2 let( :exp_class_name ) { 'DataSet' }
  68. 1 let( :exp_location ) { "/concern/data_sets/#{id}" }
  69. 1 describe 'constants' do
  70. 1 it do
  71. 1 expect( ::Deepblue::DoiBehavior::DOI_PENDING ).to eq 'doi_pending'
  72. end
  73. end
  74. 1 describe 'metadata overrides' do
  75. 1 before do
  76. 4 subject.id = id
  77. 4 subject.authoremail = authoremail
  78. 4 subject.title = [title]
  79. 4 subject.creator = [creator]
  80. 4 subject.depositor = depositor
  81. 4 subject.date_created = date_created
  82. 4 subject.description = [description]
  83. 4 subject.methodology = methodology
  84. 4 subject.rights_license = rights_license
  85. 4 subject.visibility = visibility_public
  86. end
  87. 1 it 'provides file_set_ids' do
  88. 1 key = :file_set_ids
  89. 1 exp_value = []
  90. 1 key_values = { test: 'testing' }
  91. 1 expect( subject.metadata_hash_override( key: key, ignore_blank_values: false, key_values: key_values ) ).to eq true
  92. expect( key_values[key] ).to eq exp_value
  93. expect( key_values[:test] ).to eq 'testing'
  94. expect( key_values.size ).to eq 2
  95. end
  96. 1 it 'provides total_file_size' do
  97. 1 key = :total_file_size
  98. 1 exp_value = nil
  99. 1 key_values = { test: 'testing' }
  100. 1 expect( subject.metadata_hash_override( key: key, ignore_blank_values: false, key_values: key_values ) ).to eq true
  101. 1 expect( key_values[key] ).to eq exp_value
  102. 1 expect( key_values[:test] ).to eq 'testing'
  103. 1 expect( key_values.size ).to eq 2
  104. end
  105. 1 it 'provides total_file_size_human_readable' do
  106. 1 key = :total_file_size_human_readable
  107. 1 exp_value = nil
  108. 1 key_values = { test: 'testing' }
  109. 1 expect( subject.metadata_hash_override( key: key, ignore_blank_values: false, key_values: key_values ) ).to eq true
  110. 1 expect( key_values[key] ).to eq exp_value
  111. 1 expect( key_values[:test] ).to eq 'testing'
  112. 1 expect( key_values.size ).to eq 2
  113. end
  114. 1 it 'does not provide some arbritrary metadata' do
  115. 1 key = :some_arbritrary_metadata
  116. 1 key_values = { test: 'testing' }
  117. 1 expect( subject.metadata_hash_override( key: key, ignore_blank_values: false, key_values: key_values ) ).to eq false
  118. 1 expect( key_values[:test] ).to eq 'testing'
  119. 1 expect( key_values.size ).to eq 1
  120. end
  121. end
  122. 1 describe 'provenance metadata overrides' do
  123. 1 before do
  124. 3 subject.id = id
  125. 3 subject.authoremail = authoremail
  126. 3 subject.title = [title]
  127. 3 subject.creator = [creator]
  128. 3 subject.depositor = depositor
  129. 3 subject.date_created = date_created
  130. 3 subject.description = [description]
  131. 3 subject.methodology = methodology
  132. 3 subject.rights_license = rights_license
  133. 3 subject.visibility = visibility_public
  134. end
  135. 1 it 'provides file_set_ids' do
  136. 1 prov_key_values = { test: 'testing' }
  137. 1 attribute = :file_set_ids
  138. 1 ignore_blank_key_values = false
  139. 1 expect( subject.map_provenance_attributes_override!( event: '',
  140. attribute: attribute,
  141. ignore_blank_key_values: ignore_blank_key_values,
  142. prov_key_values: prov_key_values ) ).to eq true
  143. expect( prov_key_values[:file_set_ids] ).to eq []
  144. expect( prov_key_values[:test] ).to eq 'testing'
  145. expect( prov_key_values.size ).to eq 2
  146. end
  147. 1 it 'provides visibility' do
  148. 1 prov_key_values = { test: 'testing' }
  149. 1 attribute = :visibility
  150. 1 ignore_blank_key_values = false
  151. 1 expect( subject.map_provenance_attributes_override!( event: '',
  152. attribute: attribute,
  153. ignore_blank_key_values: ignore_blank_key_values,
  154. prov_key_values: prov_key_values ) ).to eq true
  155. 1 expect( prov_key_values[:visibility] ).to eq visibility_public
  156. 1 expect( prov_key_values[:test] ).to eq 'testing'
  157. 1 expect( prov_key_values.size ).to eq 2
  158. end
  159. 1 it 'does not provide some arbritrary metadata' do
  160. 1 prov_key_values = { test: 'testing' }
  161. 1 attribute = :some_arbritrary_metadata
  162. 1 ignore_blank_key_values = false
  163. 1 expect( subject.map_provenance_attributes_override!( event: '',
  164. attribute: attribute,
  165. ignore_blank_key_values: ignore_blank_key_values,
  166. prov_key_values: prov_key_values ) ).to eq false
  167. 1 expect( prov_key_values[:test] ).to eq 'testing'
  168. 1 expect( prov_key_values.size ).to eq 1
  169. end
  170. end
  171. 1 describe 'properties' do
  172. ## TODO
  173. # it 'has private visibility when created' do
  174. # expect(subject.visibility).to eq visibility_private
  175. # end
  176. 1 it 'has subject property' do
  177. 1 expect(subject).to respond_to(:subject_discipline)
  178. end
  179. 1 it 'has identifier properties' do
  180. 1 expect(subject).to respond_to(:doi)
  181. 1 expect(subject).to respond_to(:hdl)
  182. end
  183. 1 describe 'resource type' do
  184. 1 it 'is set during initialization' do
  185. 1 expect(subject.resource_type).to eq ['Dataset']
  186. end
  187. end
  188. end
  189. 1 describe 'provenance constants' do
  190. 1 it 'has all metadata elements defined' do
  191. 1 expect( subject.attributes_all_for_provenance ).to eq metadata_keys_all
  192. end
  193. 1 it 'has brief metadata elements defined' do
  194. 1 expect( subject.attributes_brief_for_provenance ).to eq metadata_keys_brief
  195. end
  196. 1 it 'has update metadata elements defined' do
  197. 1 expect( subject.attributes_update_for_provenance ).to eq metadata_keys_update
  198. end
  199. end
  200. 1 describe 'provenance mint doi' do
  201. 1 let( :exp_despositor ) { depositor }
  202. 1 let( :exp_event ) { Deepblue::AbstractEventBehavior::EVENT_MINT_DOI }
  203. 1 let( :exp_visibility ) { visibility_public }
  204. 1 before do
  205. 2 subject.id = id
  206. 2 subject.authoremail = authoremail
  207. 2 subject.title = [title]
  208. 2 subject.creator = [creator]
  209. 2 subject.date_created = date_created
  210. 2 subject.depositor = depositor
  211. 2 subject.description = [description]
  212. 2 subject.methodology = methodology
  213. 2 subject.rights_license = rights_license
  214. end
  215. 1 it 'uses all attributes and keeps blank ones' do
  216. 1 attributes, ignore_blank_key_values = subject.attributes_for_provenance_mint_doi
  217. 1 expect( ignore_blank_key_values ).to eq Deepblue::AbstractEventBehavior::USE_BLANK_KEY_VALUES
  218. 1 expect( attributes ).to eq metadata_keys_all
  219. end
  220. 1 it 'is minted' do
  221. 1 prov_logger_received = nil
  222. 1 allow( PROV_LOGGER ).to receive( :info ) { |msg| prov_logger_received = msg }
  223. 1 before = Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now
  224. 1 expect( subject.provenance_mint_doi( current_user: current_user ) ).to eq true
  225. after = Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now
  226. validate_prov_logger_received( prov_logger_received: prov_logger_received,
  227. size: 39,
  228. before: before,
  229. after: after,
  230. exp_event: exp_event,
  231. exp_class_name: exp_class_name,
  232. exp_id: id,
  233. exp_authoremail: authoremail,
  234. exp_creator: [creator],
  235. exp_date_created: "2018-02-28",
  236. exp_description: [description],
  237. exp_depositor: exp_despositor,
  238. exp_location: exp_location,
  239. exp_methodology: methodology,
  240. exp_rights_license: rights_license,
  241. exp_visibility: exp_visibility )
  242. end
  243. end
  244. 1 describe 'provenance publish' do
  245. 1 let( :exp_despositor ) { depositor }
  246. 1 let( :exp_event ) { Deepblue::AbstractEventBehavior::EVENT_PUBLISH }
  247. 1 before do
  248. 2 subject.id = id
  249. 2 subject.authoremail = authoremail
  250. 2 subject.title = [title]
  251. 2 subject.creator = [creator]
  252. 2 subject.date_created = date_created
  253. 2 subject.depositor = depositor
  254. 2 subject.description = [description]
  255. 2 subject.methodology = methodology
  256. 2 subject.rights_license = rights_license
  257. 2 subject.visibility = visibility_public
  258. end
  259. 1 it 'uses all attributes and keeps blank ones' do
  260. 1 attributes, ignore_blank_key_values = subject.attributes_for_provenance_publish
  261. 1 expect( ignore_blank_key_values ).to eq Deepblue::AbstractEventBehavior::USE_BLANK_KEY_VALUES
  262. 1 expect( attributes ).to eq metadata_keys_all
  263. end
  264. 1 it 'is published' do
  265. 1 prov_logger_received = nil
  266. 1 allow( PROV_LOGGER ).to receive( :info ) { |msg| prov_logger_received = msg }
  267. 1 before = Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now
  268. 1 expect( subject.provenance_publish( current_user: current_user ) ).to eq true
  269. after = Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now
  270. validate_prov_logger_received( prov_logger_received: prov_logger_received,
  271. size: 40,
  272. before: before,
  273. after: after,
  274. exp_event: exp_event,
  275. exp_class_name: exp_class_name,
  276. exp_id: id,
  277. exp_authoremail: authoremail,
  278. exp_creator: [creator],
  279. exp_date_created: "2018-02-28",
  280. exp_description: [description],
  281. exp_depositor: exp_despositor,
  282. exp_location: exp_location,
  283. exp_message: '',
  284. exp_methodology: methodology,
  285. exp_rights_license: rights_license,
  286. exp_visibility: visibility_public )
  287. end
  288. end
  289. 1 describe 'provenance unpublish' do
  290. 1 let( :exp_despositor ) { depositor }
  291. 1 let( :exp_event ) { Deepblue::AbstractEventBehavior::EVENT_UNPUBLISH }
  292. 1 before do
  293. 2 subject.id = id
  294. 2 subject.authoremail = authoremail
  295. 2 subject.title = [title]
  296. 2 subject.creator = [creator]
  297. 2 subject.date_created = date_created
  298. 2 subject.depositor = depositor
  299. 2 subject.description = [description]
  300. 2 subject.methodology = methodology
  301. 2 subject.rights_license = rights_license
  302. 2 subject.visibility = visibility_private
  303. end
  304. 1 it 'uses all attributes and keeps blank ones' do
  305. 1 attributes, ignore_blank_key_values = subject.attributes_for_provenance_unpublish
  306. 1 expect( ignore_blank_key_values ).to eq Deepblue::AbstractEventBehavior::USE_BLANK_KEY_VALUES
  307. 1 expect( attributes ).to eq metadata_keys_all
  308. end
  309. 1 it 'is published' do
  310. 1 prov_logger_received = nil
  311. 1 allow( PROV_LOGGER ).to receive( :info ) { |msg| prov_logger_received = msg }
  312. 1 before = Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now
  313. 1 expect( subject.provenance_unpublish( current_user: current_user ) ).to eq true
  314. after = Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now
  315. validate_prov_logger_received( prov_logger_received: prov_logger_received,
  316. size: 39,
  317. before: before,
  318. after: after,
  319. exp_event: exp_event,
  320. exp_class_name: exp_class_name,
  321. exp_id: id,
  322. exp_authoremail: authoremail,
  323. exp_creator: [creator],
  324. exp_date_created: "2018-02-28",
  325. exp_description: [description],
  326. exp_depositor: exp_despositor,
  327. exp_location: exp_location,
  328. exp_methodology: methodology,
  329. exp_rights_license: rights_license,
  330. exp_visibility: visibility_private )
  331. end
  332. end
  333. 1 describe 'it requires core metadata' do
  334. 1 before do
  335. 6 subject.id = id
  336. 6 subject.authoremail = authoremail
  337. 6 subject.title = [title]
  338. 6 subject.creator = [creator]
  339. 6 subject.date_created = date_created
  340. 6 subject.description = [description]
  341. 6 subject.rights_license = rights_license
  342. end
  343. 1 it 'validates authoremail' do
  344. 1 subject.authoremail = nil
  345. 1 expect(subject).not_to be_valid
  346. end
  347. 1 it 'validates creator' do
  348. 1 subject.creator = []
  349. 1 expect(subject).not_to be_valid
  350. end
  351. 1 it 'validates date_created' do
  352. 1 subject.date_created = nil
  353. 1 expect(subject).not_to be_valid
  354. end
  355. 1 it 'validates description' do
  356. 1 subject.description = [description]
  357. 1 expect(subject).not_to be_valid
  358. end
  359. 1 it 'validates rights_license' do
  360. 1 subject.rights_license = nil
  361. 1 expect(subject).not_to be_valid
  362. end
  363. 1 it 'validates title' do
  364. 1 subject.title = []
  365. 1 expect(subject).not_to be_valid
  366. end
  367. end
  368. 1 describe 'it can be tombstoned' do
  369. 2 let( :epitaph ) { 'The reason for being tombstoned.' }
  370. 1 let( :depositor_at_tombstone ) { depositor }
  371. 1 let( :visibility_at_tombstone ) { visibility_public }
  372. 1 let( :exp_event ) { Deepblue::AbstractEventBehavior::EVENT_TOMBSTONE }
  373. 1 let( :exp_depositor ) { depositor }
  374. 1 let( :exp_visibility ) { visibility_private }
  375. 1 before do
  376. 1 subject.id = id
  377. 1 subject.authoremail = authoremail
  378. 1 subject.title = [title]
  379. 1 subject.creator = [creator]
  380. 1 subject.depositor = depositor
  381. 1 subject.date_created = date_created
  382. 1 subject.description = [description]
  383. 1 subject.methodology = methodology
  384. 1 subject.rights_license = rights_license
  385. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  386. end
  387. 1 it 'is tombstoned' do
  388. 1 prov_logger_received = nil
  389. 1 allow( PROV_LOGGER ).to receive( :info ) { |msg| prov_logger_received = msg }
  390. 1 before = Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now
  391. 1 expect( subject.entomb!( epitaph, current_user ) ).to eq true
  392. after = Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now
  393. validate_prov_logger_received( prov_logger_received: prov_logger_received,
  394. size: 42,
  395. before: before,
  396. after: after,
  397. exp_event: exp_event,
  398. exp_class_name: exp_class_name,
  399. exp_id: id,
  400. exp_authoremail: authoremail,
  401. exp_creator: [creator],
  402. exp_date_created: "2018-02-28",
  403. exp_description: [description],
  404. exp_depositor: exp_depositor,
  405. exp_location: exp_location,
  406. exp_methodology: methodology,
  407. exp_rights_license: rights_license,
  408. exp_tombstone: [epitaph],
  409. exp_visibility: exp_visibility,
  410. depositor_at_tombstone: depositor_at_tombstone,
  411. visibility_at_tombstone: visibility_at_tombstone )
  412. end
  413. end
  414. 1 describe 'provenance update' do
  415. 1 let( :exp_despositor ) { depositor }
  416. 2 let( :exp_event ) { Deepblue::AbstractEventBehavior::EVENT_UPDATE }
  417. 2 let( :methodology_new ) { 'The New Methodology' }
  418. 1 let( :methodology_old ) { 'The Old Methodology' }
  419. 3 let( :rights_license ) { 'The Rights License' }
  420. 3 let( :subject_discipline ) { 'The Subject Discipline' }
  421. 1 let( :form_params ) do
  422. 1 { "title": [title, ""],
  423. "creator": [creator, ""],
  424. "authoremail": authoremail,
  425. "methodology": methodology_new,
  426. "description": [description, ""],
  427. "rights_license": rights_license,
  428. "subject_discipline": [subject_discipline, ""],
  429. "fundedby": "",
  430. "fundedby_other": "",
  431. "grantnumber": "",
  432. "keyword": [""],
  433. "language": [""],
  434. "referenced_by": [""],
  435. "member_of_collection_ids": "",
  436. "find_child_work": "",
  437. "permissions_attributes": { "0": { "access": "edit", "id": "197055dd-3e5e-4714-9878-8620f2195428/39/2e/47/ca/392e47ca-b01b-4c3f-afb9-9ddb537fdacc" } },
  438. "visibility_during_embargo": "restricted",
  439. "embargo_release_date": "2018-06-30",
  440. "visibility_after_embargo": "open",
  441. "visibility_during_lease": "private",
  442. "lease_expiration_date": "2018-06-30",
  443. "visibility_after_lease": "open",
  444. "visibility": visibility_public,
  445. "version": "W/\"591319c1fdd3c69832f55e8fbbef903a4a0381a5\"",
  446. "date_coverage": "",
  447. "curation_notes_admin": [""],
  448. "curation_notes_user": [""] }
  449. end
  450. 2 let( :expected_attr_key_values ) { { UpdateAttribute_methodology: { attribute: :methodology, old_value: methodology, new_value: methodology_new } } }
  451. 2 let( :expected_added_key_values ) { { UpdateAttribute_methodology: { "attribute" => "methodology", "old_value" => "The Methodology", "new_value" => "The New Methodology" } } }
  452. 1 before do
  453. 2 subject.id = id
  454. 2 subject.authoremail = authoremail
  455. 2 subject.title = [title]
  456. 2 subject.creator = [creator]
  457. 2 subject.date_created = date_created
  458. 2 subject.depositor = depositor
  459. 2 subject.description = [description]
  460. 2 subject.methodology = methodology
  461. 2 subject.rights_license = rights_license
  462. 2 subject.subject_discipline = [subject_discipline]
  463. 2 subject.visibility = visibility_public
  464. end
  465. 1 it 'uses update attributes and discards blank ones' do
  466. 1 attributes, ignore_blank_key_values = subject.attributes_for_provenance_update
  467. 1 expect( ignore_blank_key_values ).to eq Deepblue::AbstractEventBehavior::IGNORE_BLANK_KEY_VALUES
  468. 1 expect( attributes ).to eq metadata_keys_update
  469. end
  470. 1 it 'logs provenance for update' do
  471. 1 attr_key_values = subject.provenance_log_update_before( form_params: form_params )
  472. 1 expect( attr_key_values ).to eq expected_attr_key_values
  473. 1 subject.methodology = methodology_new
  474. 1 prov_logger_received = nil
  475. 2 allow( PROV_LOGGER ).to receive( :info ) { |msg| prov_logger_received = msg }
  476. 1 before = Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now
  477. 1 subject.provenance_log_update_after( current_user: current_user, update_attr_key_values: attr_key_values )
  478. 1 after = Deepblue::ProvenanceHelper.to_log_format_timestamp Time.now
  479. 1 validate_prov_logger_received( prov_logger_received: prov_logger_received,
  480. size: 10,
  481. before: before,
  482. after: after,
  483. exp_event: exp_event,
  484. exp_class_name: exp_class_name,
  485. exp_id: id,
  486. exp_authoremail: authoremail,
  487. exp_total_file_count: nil,
  488. exp_total_file_size: nil,
  489. exp_total_file_size_human_readable: nil,
  490. exp_visibility: visibility_public,
  491. **expected_added_key_values )
  492. end
  493. end
  494. 1 def validate_expected( rv_key_values, key, exp_value )
  495. 36 key = key.to_s
  496. 36 expect( rv_key_values[key] ).to eq exp_value if exp_value.present?
  497. # the rv_key_values.key?(key) seems to have semantically changed in ruby 2.5, so skip this check until a
  498. # replacement can be figured out.
  499. # expect( rv_key_values.key?(key) ).to eq false if exp_value.nil?
  500. end
  501. 1 def validate_prov_logger_received( prov_logger_received:,
  502. size:,
  503. print_all_key_values: false,
  504. before: nil,
  505. after: nil,
  506. exp_timestamp: nil,
  507. exp_time_zone: DeepBlueDocs::Application.config.timezone_zone,
  508. exp_event:,
  509. exp_event_note: nil,
  510. exp_class_name:,
  511. exp_id:,
  512. exp_access_deepblue: '',
  513. exp_admin_set_id: '',
  514. exp_authoremail: '',
  515. exp_creator: [],
  516. exp_curation_notes_admin: [],
  517. exp_curation_notes_user: [],
  518. exp_date_coverage: '',
  519. exp_date_created: '',
  520. exp_date_modified: '',
  521. exp_date_published: '',
  522. exp_date_updated: [],
  523. exp_depositor: '',
  524. exp_description: [],
  525. exp_doi: '',
  526. exp_fundedby: '',
  527. exp_fundedby_other: '',
  528. exp_grantnumber: '',
  529. exp_referenced_by: [],
  530. exp_keyword: [],
  531. exp_language: [],
  532. exp_location: '',
  533. exp_message: '',
  534. exp_methodology: '',
  535. exp_prior_identifier: [],
  536. exp_rights_license: '',
  537. exp_rights_license_other: '',
  538. exp_subject_discipline: [],
  539. exp_title: [],
  540. exp_tombstone: [],
  541. exp_total_file_count: 0,
  542. exp_total_file_size: '',
  543. exp_total_file_size_human_readable: '',
  544. exp_visibility: '',
  545. **added_prov_key_values )
  546. 1 expect( prov_logger_received ).to be_a String
  547. rv_timestamp,
  548. rv_event,
  549. rv_event_note,
  550. rv_class_name,
  551. rv_id,
  552. 1 rv_key_values = Deepblue::ProvenanceHelper.parse_log_line prov_logger_received
  553. 1 expect( rv_timestamp ).to be_between( before, after ) if exp_timestamp.nil?
  554. 1 expect( rv_timestamp ).to eq exp_timestamp if exp_timestamp.present?
  555. 1 expect( rv_event ).to eq exp_event
  556. 1 expect( rv_event_note ).to eq exp_event_note if exp_event_note.present?
  557. 1 expect( rv_event_note ).to eq '' if exp_event_note.nil?
  558. 1 expect( rv_class_name ).to eq exp_class_name
  559. 1 expect( rv_id ).to eq exp_id
  560. 1 rv_key_values.each_pair { |key, value| puts "#{key},#{value}" } if print_all_key_values
  561. 1 expect( rv_key_values['event'] ).to eq exp_event
  562. 1 expect( rv_key_values['timestamp'] ).to be_between( before, after ) if before.present? && after.present?
  563. 1 expect( rv_key_values['timestamp'] ).to eq exp_timestamp if exp_timestamp.present?
  564. 1 expect( rv_key_values['time_zone'] ).to eq exp_time_zone if exp_time_zone.present?
  565. 1 validate_expected( rv_key_values, :event_note, exp_event_note )
  566. 1 validate_expected( rv_key_values, :class_name, exp_class_name )
  567. 1 validate_expected( rv_key_values, :id, exp_id )
  568. 1 validate_expected( rv_key_values, :admin_set_id, exp_admin_set_id )
  569. 1 validate_expected( rv_key_values, :authoremail, exp_authoremail )
  570. 1 validate_expected( rv_key_values, :creator, exp_creator )
  571. 1 validate_expected( rv_key_values, :curation_notes_admin, exp_curation_notes_admin )
  572. 1 validate_expected( rv_key_values, :curation_notes_user, exp_curation_notes_user )
  573. 1 validate_expected( rv_key_values, :date_coverage, exp_date_coverage )
  574. 1 validate_expected( rv_key_values, :date_created, exp_date_created )
  575. 1 validate_expected( rv_key_values, :date_modified, exp_date_modified )
  576. 1 validate_expected( rv_key_values, :date_published, exp_date_published )
  577. 1 validate_expected( rv_key_values, :date_updated, exp_date_updated )
  578. 1 validate_expected( rv_key_values, :depositor, exp_depositor )
  579. 1 validate_expected( rv_key_values, :description, exp_description )
  580. 1 validate_expected( rv_key_values, :doi, exp_doi )
  581. 1 validate_expected( rv_key_values, :fundedby, exp_fundedby )
  582. 1 validate_expected( rv_key_values, :fundedby_other, exp_fundedby_other )
  583. 1 validate_expected( rv_key_values, :grantnumber, exp_grantnumber )
  584. 1 validate_expected( rv_key_values, :referenced_by, exp_referenced_by )
  585. 1 validate_expected( rv_key_values, :keyword, exp_keyword )
  586. 1 validate_expected( rv_key_values, :language, exp_language )
  587. 1 validate_expected( rv_key_values, :location, exp_location )
  588. 1 validate_expected( rv_key_values, :message, exp_message )
  589. 1 validate_expected( rv_key_values, :methodology, exp_methodology )
  590. 1 validate_expected( rv_key_values, :prior_identifier, exp_prior_identifier )
  591. 1 validate_expected( rv_key_values, :rights_license, exp_rights_license )
  592. 1 validate_expected( rv_key_values, :rights_license_other, exp_rights_license_other )
  593. 1 validate_expected( rv_key_values, :subject_discipline, exp_subject_discipline )
  594. 1 validate_expected( rv_key_values, :title, exp_title )
  595. 1 validate_expected( rv_key_values, :tombstone, exp_tombstone )
  596. 1 validate_expected( rv_key_values, :total_file_count, exp_total_file_count )
  597. 1 validate_expected( rv_key_values, :total_file_size, exp_total_file_size )
  598. 1 validate_expected( rv_key_values, :total_file_size_human_readable, exp_total_file_size_human_readable )
  599. 1 validate_expected( rv_key_values, :visibility, exp_visibility )
  600. 1 added_prov_key_values.each_pair do |key, value|
  601. 1 validate_expected(rv_key_values, key, value )
  602. end
  603. 1 expect( rv_key_values.size ).to eq size
  604. end
  605. end

spec/models/dissertation_spec.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work Dissertation`
  3. 1 require 'rails_helper'
  4. 1 RSpec.describe Dissertation do
  5. 1 it "has tests" do
  6. 1 skip "Add your tests here"
  7. end
  8. end

spec/models/file_set_spec.rb

78.05% lines covered

123 relevant lines. 96 lines covered and 27 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'rails_helper'
  3. 1 RSpec.describe FileSet do
  4. # include Hyrax::FactoryHelpers
  5. # before(:all) do
  6. # #puts "DataSet ids before=#{DataSet.all.map { |ds| ds.id }}"
  7. # puts "FileSet ids before=#{FileSet.all.map { |fs| fs.id }}"
  8. # end
  9. #
  10. # after(:all) do
  11. # puts "FileSet ids after=#{FileSet.all.map { |fs| fs.id }}"
  12. # #puts "DataSet ids after=#{DataSet.all.map { |ds| ds.id }}"
  13. # # clean up created DataSet
  14. # #DataSet.all.each { |ds| ds.delete }
  15. # FileSet.all.each { |fs| fs.delete }
  16. # end
  17. 5 let( :id ) { '0123458678' }
  18. 1 let( :visibility_private ) { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE }
  19. 1 let( :visibility_public ) { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC }
  20. 1 let( :metadata_keys_all ) {
  21. 1 %i[
  22. curation_notes_admin
  23. curation_notes_user
  24. date_created
  25. date_modified
  26. date_uploaded
  27. file_extension
  28. files_count
  29. file_size
  30. file_size_human_readable
  31. label
  32. location
  33. mime_type
  34. original_checksum
  35. original_name
  36. parent_id
  37. prior_identifier
  38. title
  39. uri
  40. version_count
  41. virus_scan_service
  42. virus_scan_status
  43. virus_scan_status_date
  44. visibility
  45. ]
  46. }
  47. 1 let( :metadata_keys_brief ) {
  48. 1 %i[
  49. title
  50. label
  51. parent_id
  52. file_extension
  53. visibility
  54. ]
  55. }
  56. 1 let( :metadata_keys_update ) {
  57. 1 %i[
  58. title
  59. label
  60. parent_id
  61. file_extension
  62. version_count
  63. visibility
  64. ]
  65. }
  66. 1 let(:user) { create(:user) }
  67. 1 describe 'provenance constants' do
  68. 1 it 'has all metadata elements defined' do
  69. 1 expect( subject.attributes_all_for_provenance ).to eq metadata_keys_all
  70. end
  71. 1 it 'has brief metadata elements defined' do
  72. 1 expect( subject.attributes_brief_for_provenance ).to eq metadata_keys_brief
  73. end
  74. 1 it 'has update metadata elements defined' do
  75. 1 expect( subject.attributes_update_for_provenance ).to eq metadata_keys_update
  76. end
  77. end
  78. 1 describe 'rdf type' do
  79. 2 subject { described_class.new.type }
  80. 2 it { is_expected.to include(Hydra::PCDM::Vocab::PCDMTerms.Object, Hydra::Works::Vocab::WorksTerms.FileSet) }
  81. end
  82. 1 it 'is a Hydra::Works::FileSet' do
  83. 1 expect(subject).to be_file_set
  84. end
  85. 1 it 'has depositor' do
  86. 1 subject.depositor = 'tess@example.com'
  87. end
  88. 1 it 'updates attributes' do
  89. 1 subject.attributes = { title: ['My new Title'] }
  90. 1 expect(subject.title).to eq(['My new Title'])
  91. end
  92. 1 context 'when it is initialized' do
  93. 1 it 'has empty arrays for the properties' do
  94. 1 expect(subject.title).to eq []
  95. end
  96. end
  97. 1 describe 'visibility' do
  98. 1 it "does not be changed when it's new" do
  99. 1 expect(subject).not_to be_visibility_changed
  100. end
  101. 1 it 'is changed when it has been changed' do
  102. 1 subject.visibility = 'open'
  103. 1 expect(subject).to be_visibility_changed
  104. end
  105. 1 it "does not be changed when it's set to its previous value" do
  106. 1 subject.visibility = 'restricted'
  107. 1 expect(subject).not_to be_visibility_changed
  108. end
  109. end
  110. 1 describe '#apply_depositor_metadata' do
  111. 2 before { subject.apply_depositor_metadata('jcoyne') }
  112. 1 it 'grants edit access and record the depositor' do
  113. 1 expect(subject.edit_users).to eq ['jcoyne']
  114. 1 expect(subject.depositor).to eq 'jcoyne'
  115. end
  116. end
  117. 1 describe 'attributes' do
  118. 1 it 'has a set of permissions' do
  119. 1 subject.read_groups = %w[group1 group2]
  120. 1 subject.edit_users = ['user1']
  121. 1 subject.read_users = %w[user2 user3]
  122. 1 expect(subject.permissions.map(&:to_hash)).to match_array [
  123. { type: 'group', access: 'read', name: 'group1' },
  124. { type: 'group', access: 'read', name: 'group2' },
  125. { type: 'person', access: 'read', name: 'user2' },
  126. { type: 'person', access: 'read', name: 'user3' },
  127. { type: 'person', access: 'edit', name: 'user1' }
  128. ]
  129. end
  130. 1 it "has attached content" do
  131. 1 expect(subject.association(:original_file)).to be_kind_of ActiveFedora::Associations::DirectlyContainsOneAssociation
  132. end
  133. end
  134. 1 describe 'metadata' do
  135. 1 it 'has descriptive metadata' do
  136. 1 expect(subject).to respond_to(:relative_path)
  137. 1 expect(subject).to respond_to(:depositor)
  138. 1 expect(subject).to respond_to(:related_url)
  139. 1 expect(subject).to respond_to(:based_near)
  140. 1 expect(subject).to respond_to(:contributor)
  141. 1 expect(subject).to respond_to(:creator)
  142. 1 expect(subject).to respond_to(:title)
  143. 1 expect(subject).to respond_to(:description)
  144. 1 expect(subject).to respond_to(:publisher)
  145. 1 expect(subject).to respond_to(:date_created)
  146. 1 expect(subject).to respond_to(:date_uploaded)
  147. 1 expect(subject).to respond_to(:date_modified)
  148. 1 expect(subject).to respond_to(:subject)
  149. 1 expect(subject).to respond_to(:language)
  150. 1 expect(subject).to respond_to(:license)
  151. 1 expect(subject).to respond_to(:resource_type)
  152. 1 expect(subject).to respond_to(:identifier)
  153. end
  154. 1 it 'has properties from characterization metadata' do
  155. 1 expect(subject).to respond_to(:format_label)
  156. 1 expect(subject).to respond_to(:mime_type)
  157. 1 expect(subject).to respond_to(:file_size)
  158. 1 expect(subject).to respond_to(:last_modified)
  159. 1 expect(subject).to respond_to(:filename)
  160. 1 expect(subject).to respond_to(:original_checksum)
  161. 1 expect(subject).to respond_to(:well_formed)
  162. 1 expect(subject).to respond_to(:page_count)
  163. 1 expect(subject).to respond_to(:file_title)
  164. 1 expect(subject).to respond_to(:duration)
  165. 1 expect(subject).to respond_to(:sample_rate)
  166. # :creator is characterization metadata?
  167. 1 expect(subject).to respond_to(:creator)
  168. end
  169. 1 describe 'metadata overrides' do
  170. 1 before do
  171. 4 subject.id = id
  172. 4 subject.label = "some_file.pdf"
  173. subject.visibility = visibility_public
  174. end
  175. 1 it 'provides file_set_ids' do
  176. key = :label
  177. exp_value = "some_file.pdf"
  178. key_values = { test: 'testing' }
  179. expect( subject.metadata_hash_override( key: key, ignore_blank_values: false, key_values: key_values ) ).to eq true
  180. expect( key_values[key] ).to eq exp_value
  181. expect( key_values[:test] ).to eq 'testing'
  182. expect( key_values.size ).to eq 2
  183. end
  184. 1 it 'provides file_size' do
  185. key = :file_size
  186. exp_value = 0
  187. key_values = { test: 'testing' }
  188. expect( subject.metadata_hash_override( key: key, ignore_blank_values: false, key_values: key_values ) ).to eq true
  189. expect( key_values[key] ).to eq exp_value
  190. expect( key_values[:test] ).to eq 'testing'
  191. expect( key_values.size ).to eq 2
  192. end
  193. 1 it 'provides file_size_human_readable' do
  194. key = :file_size_human_readable
  195. exp_value = '0 Bytes'
  196. key_values = { test: 'testing' }
  197. expect( subject.metadata_hash_override( key: key, ignore_blank_values: false, key_values: key_values ) ).to eq true
  198. expect( key_values[key] ).to eq exp_value
  199. expect( key_values[:test] ).to eq 'testing'
  200. expect( key_values.size ).to eq 2
  201. end
  202. 1 it 'does not provide some arbritrary metadata' do
  203. key = :some_arbritrary_metadata
  204. key_values = { test: 'testing' }
  205. expect( subject.metadata_hash_override( key: key, ignore_blank_values: false, key_values: key_values ) ).to eq false
  206. expect( key_values[:test] ).to eq 'testing'
  207. expect( key_values.size ).to eq 1
  208. end
  209. end
  210. 1 it 'redefines to_param to make redis keys more recognizable' do
  211. 1 expect(subject.to_param).to eq subject.id
  212. end
  213. # describe 'that have been saved' do
  214. # before { subject.apply_depositor_metadata('jcoyne') }
  215. #
  216. # it 'is able to set values via delegated methods' do
  217. # subject.related_url = ['http://example.org/']
  218. # subject.creator = ['John Doe']
  219. # subject.title = ['New work']
  220. # subject.save
  221. # f = subject.reload
  222. # expect(f.related_url).to eq ['http://example.org/']
  223. # expect(f.creator).to eq ['John Doe']
  224. # expect(f.title).to eq ['New work']
  225. # end
  226. #
  227. # it 'is able to be added to w/o unexpected graph behavior' do
  228. # subject.creator = ['John Doe']
  229. # subject.title = ['New work']
  230. # subject.save!
  231. # f = subject.reload
  232. # expect(f.creator).to eq ['John Doe']
  233. # expect(f.title).to eq ['New work']
  234. # f.creator = ['Jane Doe']
  235. # f.title += ['Newer work']
  236. # f.save
  237. # f = subject.reload
  238. # expect(f.creator).to eq ['Jane Doe']
  239. # # TODO: Is order important?
  240. # expect(f.title).to include('New work')
  241. # expect(f.title).to include('Newer work')
  242. # end
  243. # end
  244. end
  245. # describe '#indexer' do
  246. # subject { described_class.indexer }
  247. #
  248. # it { is_expected.to eq Hyrax::FileSetIndexer }
  249. #
  250. # describe "setting" do
  251. # before do
  252. # class AltFile < ActiveFedora::Base
  253. # include Hyrax::FileSetBehavior
  254. # end
  255. # end
  256. # after do
  257. # Object.send(:remove_const, :AltFile)
  258. # end
  259. # let(:klass) { Class.new }
  260. #
  261. # subject { AltFile.new }
  262. #
  263. # it 'is settable' do
  264. # AltFile.indexer = klass
  265. # expect(AltFile.indexer).to eq klass
  266. # end
  267. # end
  268. # end
  269. #
  270. # it 'supports multi-valued fields in solr' do
  271. # subject.keyword = %w[keyword1 keyword2]
  272. # expect { subject.save }.not_to raise_error
  273. # subject.delete
  274. # end
  275. #
  276. # it 'supports setting and getting the relative_path value' do
  277. # subject.relative_path = 'documents/research/NSF/2010'
  278. # expect(subject.relative_path).to eq 'documents/research/NSF/2010'
  279. # end
  280. # describe 'create_thumbnail' do
  281. # let(:file_set) do
  282. # described_class.new do |f|
  283. # f.apply_depositor_metadata('mjg36')
  284. # end
  285. # end
  286. #
  287. # describe 'with a video', if: Hyrax.config.enable_ffmpeg do
  288. # before do
  289. # allow(file_set).to receive(mime_type: 'video/quicktime') # Would get set by the characterization job
  290. # file_set.save
  291. # Hydra::Works::AddFileToFileSet.call(subject, File.open("#{fixture_path}/countdown.avi", 'rb'), :original_file)
  292. # end
  293. # it 'makes a png thumbnail' do
  294. # file_set.create_thumbnail
  295. # expect(file_set.thumbnail.content.size).to eq 4768 # this is a bad test. I just want to show that it did something.
  296. # expect(file_set.thumbnail.mime_type).to eq 'image/png'
  297. # end
  298. # end
  299. # end
  300. #
  301. # describe '#related_files' do
  302. # let!(:f1) { described_class.new }
  303. #
  304. # context 'when there are no related files' do
  305. # it 'returns an empty array' do
  306. # expect(f1.related_files).to eq []
  307. # end
  308. # end
  309. #
  310. # context 'when there are related files' do
  311. # let(:parent_work) { create(:data_set_with_files) }
  312. # let(:f1) { parent_work.file_sets.first }
  313. # let(:f2) { parent_work.file_sets.last }
  314. #
  315. # subject { f1.reload.related_files }
  316. #
  317. # it 'returns all files contained in parent work(s) but excludes itself' do
  318. # expect(subject).to include(f2)
  319. # expect(subject).not_to include(f1)
  320. # end
  321. # end
  322. # end
  323. #
  324. # describe 'noid integration', :clean_repo do
  325. # let(:service) { instance_double(::Noid::Rails::Service, mint: noid) }
  326. # let(:noid) { 'wd3763094' }
  327. # let!(:default) { Hyrax.config.enable_noids? }
  328. #
  329. # before do
  330. # allow(::Noid::Rails::Service).to receive(:new).and_return(service)
  331. # end
  332. #
  333. # after { Hyrax.config.enable_noids = default }
  334. #
  335. # context 'with noids enabled' do
  336. # before { Hyrax.config.enable_noids = true }
  337. #
  338. # it 'uses the noid service' do
  339. # expect(service).to receive(:mint).once
  340. # subject.assign_id
  341. # end
  342. #
  343. # context "after saving" do
  344. # before { subject.save! }
  345. #
  346. # it 'returns the expected identifier' do
  347. # expect(subject.id).to eq noid
  348. # end
  349. #
  350. # it "has a treeified URL" do
  351. # expect(subject.uri.to_s).to end_with '/wd/37/63/09/wd3763094'
  352. # end
  353. # end
  354. #
  355. # context 'when a url is provided' do
  356. # let(:url) { "#{ActiveFedora.fedora.host}/test/wd/37/63/09/wd3763094" }
  357. #
  358. # it 'transforms the url into an id' do
  359. # expect(described_class.uri_to_id(url)).to eq 'wd3763094'
  360. # end
  361. # end
  362. # end
  363. #
  364. # context 'with noids disabled' do
  365. # before { Hyrax.config.enable_noids = false }
  366. #
  367. # it 'does not use the noid service' do
  368. # expect(service).not_to receive(:mint)
  369. # subject.assign_id
  370. # end
  371. # end
  372. # end
  373. #
  374. # context 'with access control metadata' do
  375. # subject do
  376. # described_class.new do |m|
  377. # m.apply_depositor_metadata('jcoyne')
  378. # m.permissions_attributes = [{ type: 'person', access: 'read', name: 'person1' },
  379. # { type: 'person', access: 'read', name: 'person2' },
  380. # { type: 'group', access: 'read', name: 'group-6' },
  381. # { type: 'group', access: 'read', name: 'group-7' },
  382. # { type: 'group', access: 'edit', name: 'group-8' }]
  383. # end
  384. # end
  385. #
  386. # it 'has read groups accessor' do
  387. # expect(subject.read_groups).to eq ['group-6', 'group-7']
  388. # end
  389. #
  390. # it 'has read groups writer' do
  391. # subject.read_groups = ['group-2', 'group-3']
  392. # expect(subject.read_groups).to eq ['group-2', 'group-3']
  393. # end
  394. # end
  395. #
  396. # describe 'permissions validation' do
  397. # before { subject.apply_depositor_metadata('mjg36') }
  398. #
  399. # describe 'overriding' do
  400. # let(:asset) { SampleKlass.new }
  401. #
  402. # before do
  403. # class SampleKlass < FileSet
  404. # def paranoid_edit_permissions
  405. # []
  406. # end
  407. # end
  408. # asset.apply_depositor_metadata('mjg36')
  409. # end
  410. # after do
  411. # Object.send(:remove_const, :SampleKlass)
  412. # end
  413. # context 'when the public has edit access' do
  414. # before { subject.edit_groups = ['public'] }
  415. #
  416. # it 'is invalid' do
  417. # expect(subject).not_to be_valid
  418. # expect(subject.errors[:edit_groups]).to include('Public cannot have edit access')
  419. # end
  420. # end
  421. # end
  422. #
  423. # describe '#paranoid_edit_permissions=' do
  424. # before do
  425. # subject.paranoid_edit_permissions =
  426. # [
  427. # { key: :edit_users, message: 'Depositor must have edit access', condition: ->(obj) { !obj.edit_users.include?(obj.depositor) } }
  428. # ]
  429. # subject.permissions = [Hydra::AccessControls::Permission.new(type: 'person', name: 'mjg36', access: 'read')]
  430. # end
  431. # it 'uses the user supplied configuration for validation' do
  432. # expect(subject).not_to be_valid
  433. # expect(subject.errors[:edit_users]).to include('Depositor must have edit access')
  434. # end
  435. # end
  436. #
  437. # context 'when the public has edit access' do
  438. # before { subject.edit_groups = ['public'] }
  439. #
  440. # it 'is invalid' do
  441. # expect(subject).not_to be_valid
  442. # expect(subject.errors[:edit_groups]).to include('Public cannot have edit access')
  443. # end
  444. # end
  445. #
  446. # context 'when registered has edit access' do
  447. # before { subject.edit_groups = ['registered'] }
  448. #
  449. # it 'is invalid' do
  450. # expect(subject).not_to be_valid
  451. # expect(subject.errors[:edit_groups]).to include('Registered cannot have edit access')
  452. # end
  453. # end
  454. #
  455. # context 'everything is copacetic' do
  456. # it 'is valid' do
  457. # expect(subject).to be_valid
  458. # end
  459. # end
  460. # end
  461. #
  462. # describe 'file content validation' do
  463. # subject { create(:file_set) }
  464. #
  465. # let(:file_path) { fixture_path + '/small_file.txt' }
  466. #
  467. # context 'when file contains a virus' do
  468. # before do
  469. # allow(subject).to receive(:warn) # suppress virus warnings
  470. # allow(Hydra::Works::VirusCheckerService).to receive(:file_has_virus?) { true }
  471. # # TODO: Test that this works with Hydra::Works::UploadFileToFileSet. see https://github.com/samvera/hydra-works/pull/139
  472. # # Hydra::Works::UploadFileToFileSet.call(subject, file_path, original_name: 'small_file.txt')
  473. # of = subject.build_original_file
  474. # of.content = File.open(file_path)
  475. # end
  476. #
  477. # it 'populates the errors hash during validation' do
  478. # expect(subject).not_to be_valid
  479. # expect(subject.errors.messages[:base].first).to eq "Failed to verify uploaded file is not a virus"
  480. # end
  481. #
  482. # it 'does not save the file or create a new version' do
  483. # original_version_count = subject.versions.count
  484. # subject.save
  485. # expect(subject.versions.count).to eq original_version_count
  486. # expect(subject.reload.original_file).to be_nil
  487. # end
  488. # end
  489. # end
  490. #
  491. # describe '#where_digest_is', :clean_repo do
  492. # let(:file) { create(:file_set) }
  493. # let(:file_path) { fixture_path + '/small_file.txt' }
  494. # let(:digest_string) { '88fb4e88c15682c18e8b19b8a7b6eaf8770d33cf' }
  495. #
  496. # before do
  497. # allow(file).to receive(:warn) # suppress virus warnings
  498. # of = file.build_original_file
  499. # of.content = File.open(file_path)
  500. # file.save
  501. # file.update_index
  502. # end
  503. # subject { described_class.where_digest_is(digest_string).first }
  504. #
  505. # it { is_expected.to eq(file) }
  506. # end
  507. #
  508. # describe 'to_solr' do
  509. # let(:indexer) { double(generate_solr_document: {}) }
  510. #
  511. # before do
  512. # allow(Hyrax::FileSetIndexer).to receive(:new)
  513. # .with(subject).and_return(indexer)
  514. # end
  515. #
  516. # it 'calls the indexer' do
  517. # expect(indexer).to receive(:generate_solr_document)
  518. # subject.to_solr
  519. # end
  520. #
  521. # it 'has human readable type' do
  522. # expect(subject.to_solr.fetch('human_readable_type_tesim')).to eq 'File'
  523. # end
  524. # end
  525. #
  526. # context 'with versions' do
  527. # it 'has versions' do
  528. # expect(subject.versions.count).to eq 0
  529. # end
  530. # end
  531. #
  532. # describe 'public?' do
  533. # context 'when read group is set to public' do
  534. # before { subject.read_groups = ['public'] }
  535. #
  536. # it { is_expected.to be_public }
  537. # end
  538. #
  539. # context 'when read group is not set to public' do
  540. # before { subject.read_groups = ['foo'] }
  541. # it { is_expected.not_to be_public }
  542. # end
  543. # end
  544. #
  545. # describe 'work associations' do
  546. # let(:work) { create(:data_set_with_one_file) }
  547. #
  548. # subject { work.file_sets.first.reload }
  549. #
  550. # it 'belongs to works' do
  551. # expect(subject.parents).to eq [work]
  552. # end
  553. # end
  554. #
  555. # describe '#to_s' do
  556. # it 'uses the provided titles' do
  557. # # The title property would return the terms in random order, so stub the behavior:
  558. # subject.title = %w[Hello World]
  559. # expect(subject.to_s).to include 'Hello'
  560. # expect(subject.to_s).to include 'World'
  561. # end
  562. #
  563. # it 'falls back on label if no titles are given' do
  564. # subject.title = []
  565. # subject.label = 'Spam'
  566. # expect(subject.to_s).to eq('Spam')
  567. # end
  568. #
  569. # it 'with no label or titles it is "No Title"' do
  570. # subject.title = []
  571. # subject.label = nil
  572. # expect(subject.to_s).to eq('No Title')
  573. # end
  574. # end
  575. #
  576. # describe 'to_solr record' do
  577. # subject do
  578. # described_class.new.tap do |f|
  579. # f.apply_depositor_metadata(depositor)
  580. # f.save
  581. # end
  582. # end
  583. #
  584. # let(:depositor) { 'jcoyne' }
  585. # let(:depositor_key) { Solrizer.solr_name('depositor') }
  586. # let(:title_key) { Solrizer.solr_name('title', :stored_searchable, type: :string) }
  587. # let(:title) { ['abc123'] }
  588. # let(:no_terms) { described_class.find(subject.id).to_solr }
  589. # let(:terms) do
  590. # file = described_class.find(subject.id)
  591. # file.title = title
  592. # file.save
  593. # file.to_solr
  594. # end
  595. #
  596. # context 'without terms' do
  597. # specify 'title is nil' do
  598. # expect(no_terms[title_key]).to be_nil
  599. # end
  600. # end
  601. #
  602. # context 'with terms' do
  603. # specify 'depositor is set' do
  604. # expect(terms[depositor_key].first).to eql(depositor)
  605. # end
  606. # specify 'title is set' do
  607. # expect(terms[title_key]).to eql(title)
  608. # end
  609. # end
  610. # end
  611. #
  612. # describe 'with a parent work' do
  613. # let(:parent) { create(:data_set_with_one_file) }
  614. # let(:parent_id) { parent.id }
  615. #
  616. # describe '#related_files' do
  617. # let(:parent) { create(:data_set_with_files) }
  618. # let(:sibling) { parent.file_sets.last }
  619. #
  620. # subject { parent.file_sets.first.reload }
  621. #
  622. # it 'returns related files, but not itself' do
  623. # expect(subject.related_files).to eq([sibling])
  624. # expect(sibling.reload.related_files).to eq([subject])
  625. # end
  626. # end
  627. #
  628. # describe '#remove_representative_relationship' do
  629. # subject { parent.file_sets.first.reload }
  630. #
  631. # context 'it is not the representative' do
  632. # let(:some_other_id) { create(:file_set).id }
  633. #
  634. # before do
  635. # parent.representative_id = some_other_id
  636. # parent.save!
  637. # end
  638. #
  639. # it "doesn't update parent work when file is deleted" do
  640. # subject.destroy
  641. # expect(parent.representative_id).to eq some_other_id
  642. # end
  643. # end
  644. #
  645. # context 'it is the representative' do
  646. # before do
  647. # parent.representative_id = subject.id
  648. # parent.save!
  649. # end
  650. #
  651. # it 'updates the parent work when the file is deleted' do
  652. # subject.destroy
  653. # expect(parent.reload.representative_id).to be_nil
  654. # end
  655. # end
  656. # end
  657. # end
  658. #
  659. # describe 'mime type recognition' do
  660. # let(:mock_file) { mock_file_factory(mime_type: mime_type) }
  661. #
  662. # before { allow(subject).to receive(:original_file).and_return(mock_file) }
  663. #
  664. # context '#image?' do
  665. # context 'when image/jp2' do
  666. # let(:mime_type) { 'image/jp2' }
  667. #
  668. # it { is_expected.to be_image }
  669. # end
  670. # context 'when image/jpg' do
  671. # let(:mime_type) { 'image/jpg' }
  672. #
  673. # it { is_expected.to be_image }
  674. # end
  675. # context 'when image/png' do
  676. # let(:mime_type) { 'image/png' }
  677. #
  678. # it { is_expected.to be_image }
  679. # end
  680. # context 'when image/tiff' do
  681. # let(:mime_type) { 'image/tiff' }
  682. #
  683. # it { is_expected.to be_image }
  684. # end
  685. # end
  686. #
  687. # describe '#pdf?' do
  688. # let(:mime_type) { 'application/pdf' }
  689. #
  690. # it { is_expected.to be_pdf }
  691. # end
  692. #
  693. # describe '#audio?' do
  694. # context 'when x-wave' do
  695. # let(:mime_type) { 'audio/x-wave' }
  696. #
  697. # it { is_expected.to be_audio }
  698. # end
  699. # context 'when x-wav' do
  700. # let(:mime_type) { 'audio/x-wav' }
  701. #
  702. # it { is_expected.to be_audio }
  703. # end
  704. # context 'when mpeg' do
  705. # let(:mime_type) { 'audio/mpeg' }
  706. #
  707. # it { is_expected.to be_audio }
  708. # end
  709. # context 'when mp3' do
  710. # let(:mime_type) { 'audio/mp3' }
  711. #
  712. # it { is_expected.to be_audio }
  713. # end
  714. # context 'when ogg' do
  715. # let(:mime_type) { 'audio/ogg' }
  716. #
  717. # it { is_expected.to be_audio }
  718. # end
  719. # end
  720. #
  721. # describe '#video?' do
  722. # context 'should be true for avi' do
  723. # let(:mime_type) { 'video/avi' }
  724. #
  725. # it { is_expected.to be_video }
  726. # end
  727. #
  728. # context 'should be true for webm' do
  729. # let(:mime_type) { 'video/webm' }
  730. #
  731. # it { is_expected.to be_video }
  732. # end
  733. # context 'should be true for mp4' do
  734. # let(:mime_type) { 'video/mp4' }
  735. #
  736. # it { is_expected.to be_video }
  737. # end
  738. # context 'should be true for mpeg' do
  739. # let(:mime_type) { 'video/mpeg' }
  740. #
  741. # it { is_expected.to be_video }
  742. # end
  743. # context 'should be true for quicktime' do
  744. # let(:mime_type) { 'video/quicktime' }
  745. #
  746. # it { is_expected.to be_video }
  747. # end
  748. # context 'should be true for mxf' do
  749. # let(:mime_type) { 'application/mxf' }
  750. #
  751. # it { is_expected.to be_video }
  752. # end
  753. # end
  754. # end
  755. #
  756. # describe "#to_global_id", clean_repo: true do
  757. # let(:file_set) { described_class.new(id: '123') }
  758. #
  759. # subject { file_set.to_global_id }
  760. #
  761. # it { is_expected.to be_kind_of GlobalID }
  762. # end
  763. #
  764. end

spec/models/generic_work_spec.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work GenericWork`
  3. 1 require 'rails_helper'
  4. 1 RSpec.describe GenericWork do
  5. 1 it "has tests" do
  6. 1 skip "Add your tests here"
  7. end
  8. end

spec/models/qa/local_authority_entry_spec.rb

100.0% lines covered

3 relevant lines. 3 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe Qa::LocalAuthorityEntry, type: :model do
  3. 1 pending "add some examples to (or delete) #{__FILE__}"
  4. end

spec/models/qa/local_authority_spec.rb

100.0% lines covered

3 relevant lines. 3 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe Qa::LocalAuthority, type: :model do
  3. 1 pending "add some examples to (or delete) #{__FILE__}"
  4. end

spec/models/search_builder_spec.rb

100.0% lines covered

7 relevant lines. 7 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 describe SearchBuilder do # rubocop:disable RSpec/EmptyExampleGroup
  3. 1 subject(:search_builder) { described_class.new scope }
  4. 1 let(:user_params) { {} }
  5. 1 let(:blacklight_config) { Blacklight::Configuration.new }
  6. 1 let(:scope) { double blacklight_config: blacklight_config }
  7. 1 describe "my custom step" do # rubocop:disable RSpec/EmptyExampleGroup
  8. # subject(:query_parameters) do
  9. # search_builder.with(user_params).processed_parameters
  10. # end
  11. #
  12. # it "adds my custom data" do
  13. # expect(query_parameters).to include :custom_data
  14. # end
  15. end
  16. end

spec/models/user_spec.rb

100.0% lines covered

33 relevant lines. 33 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe User, type: :model do
  3. 4 let(:user) { build(:user) }
  4. 1 let(:another_user) { build(:user) }
  5. 1 describe 'verifying factories' do
  6. 1 describe ':user' do
  7. 2 let(:user) { build(:user) }
  8. 1 it 'will, by default, have only registered group' do
  9. 1 expect(user.groups).to eq([])
  10. 1 user.save!
  11. # Ensuring that we can refind it and have the correct groups
  12. 1 expect(user.class.find(user.id).groups).to eq(['registered'])
  13. end
  14. end
  15. 1 describe ':admin' do
  16. 3 let(:admin_user) { create(:admin) }
  17. 1 it 'will be an "admin"' do
  18. 1 expect(admin_user.admin?).to be true
  19. end
  20. 1 context 'when found from the database' do
  21. 1 it 'will be an "admin"' do
  22. 1 refound_admin_user = described_class.find(admin_user.id)
  23. 1 expect(refound_admin_user.admin?).to be true
  24. end
  25. end
  26. end
  27. end
  28. 1 it "has an email" do
  29. 1 expect(user.user_key).to be_kind_of String
  30. end
  31. 1 it "has activity stream-related methods defined" do
  32. 1 expect(user).to respond_to(:stream)
  33. 1 expect(user).to respond_to(:events)
  34. 1 expect(user).to respond_to(:profile_events)
  35. 1 expect(user).to respond_to(:log_event)
  36. 1 expect(user).to respond_to(:log_profile_event)
  37. end
  38. 1 it "has social attributes" do
  39. 1 expect(user).to respond_to(:twitter_handle)
  40. 1 expect(user).to respond_to(:facebook_handle)
  41. 1 expect(user).to respond_to(:googleplus_handle)
  42. 1 expect(user).to respond_to(:linkedin_handle)
  43. 1 expect(user).to respond_to(:orcid)
  44. end
  45. # describe 'Arkivo and Zotero integration' do
  46. # it 'sets an Arkivo token after_initialize if API is enabled' do
  47. # expect(described_class.new).to respond_to(:arkivo_token)
  48. # end
  49. #
  50. # describe 'Arkivo token generation' do
  51. # before do
  52. # allow(SecureRandom).to receive(:base64).with(24).and_return(token1, token1, token2)
  53. # end
  54. #
  55. # let(:token1) { 'token1' }
  56. # let(:token2) { 'token2' }
  57. #
  58. # it 'generates a new token if a user is found with the existing token' do
  59. # user1 = described_class.create(email: 'foo@example.org', password: 'foobarbaz')
  60. # expect(user1.arkivo_token).to eq token1
  61. # user2 = described_class.create(email: 'bar@example.org', password: 'bazquuxquuux')
  62. # expect(user2.arkivo_token).to eq token2
  63. # end
  64. # end
  65. #
  66. # describe 'Zotero tokens' do
  67. # let(:token) { 'something' }
  68. #
  69. # it 'has a custom getter/setter for Zotero request tokens' do
  70. # user.zotero_token = token
  71. # expect(user.read_attribute(:zotero_token)).to eq Marshal.dump(token)
  72. # expect(user.zotero_token).to eq token
  73. # end
  74. # end
  75. # end
  76. #
  77. # describe 'ORCID validation and normalization' do
  78. # it 'saves when a valid bare ORCID is supplied' do
  79. # user.orcid = '0000-0000-1111-2222'
  80. # expect(user).to be_valid
  81. # expect(user.save).to be true
  82. # end
  83. # it 'saves when an ORCID with a non-numeric check digit is provided' do
  84. # user.orcid = 'http://orcid.org/0000-0000-1111-222X'
  85. # expect(user).to be_valid
  86. # expect(user.save).to be true
  87. # end
  88. # it 'saves when a valid ORCID HTTP URI w/ trailing slash is supplied' do
  89. # user.orcid = 'http://orcid.org/0000-0000-1111-2222/'
  90. # expect(user).to be_valid
  91. # expect(user.save).to be true
  92. # end
  93. # it 'saves when a valid ORCID HTTPS URI is supplied' do
  94. # user.orcid = 'https://orcid.org/0000-0000-1111-2222'
  95. # expect(user).to be_valid
  96. # expect(user.save).to be true
  97. # end
  98. # it 'normalizes bare ORCIDs to HTTPS URIs' do
  99. # user.orcid = '0000-0000-1111-2222'
  100. # user.save
  101. # expect(user.orcid).to eq 'https://orcid.org/0000-0000-1111-2222'
  102. # end
  103. # it 'normalizes HTTP ORCIDs to HTTPS URIs' do
  104. # user.orcid = 'http://orcid.org/0000-0000-1111-2222'
  105. # user.save
  106. # expect(user.orcid).to eq 'https://orcid.org/0000-0000-1111-2222'
  107. # end
  108. # it 'marks short ORCIDs as invalid' do
  109. # user.orcid = '000-000-111-222'
  110. # expect(user).not_to be_valid
  111. # expect(user.save).to be false
  112. # end
  113. # it 'marks long ORCIDs as invalid' do
  114. # user.orcid = '0000-0000-1111-222222'
  115. # expect(user).not_to be_valid
  116. # expect(user.save).to be false
  117. # end
  118. # end
  119. #
  120. # describe "#to_param" do
  121. # let(:user) { described_class.new(email: 'jilluser@example.com') }
  122. #
  123. # it "overrides to_param to make keys more recognizable in redis (and useable within Rails URLs)" do
  124. # expect(user.to_param).to eq("jilluser@example-dot-com")
  125. # end
  126. # end
  127. #
  128. # subject { user }
  129. #
  130. # it { is_expected.to delegate_method(:can?).to(:ability) }
  131. # it { is_expected.to delegate_method(:cannot?).to(:ability) }
  132. #
  133. # describe '#to_sipity_agent' do
  134. # subject { user.to_sipity_agent }
  135. #
  136. # it 'will find or create a Sipity::Agent' do
  137. # user.save!
  138. # expect { subject }.to change { Sipity::Agent.count }.by(1)
  139. # end
  140. #
  141. # it 'will fail if the User is not persisted' do
  142. # expect { subject }.to raise_error(ActiveRecord::StatementInvalid)
  143. # end
  144. #
  145. # context "when another process makes the agent" do
  146. # let(:user) { create(:user) }
  147. #
  148. # before do
  149. # user.sipity_agent # load up and cache the association
  150. # User.find(user.id).create_sipity_agent!
  151. # end
  152. # it "returns the existing agent" do
  153. # expect { subject }.not_to change { Sipity::Agent.count }
  154. # end
  155. # end
  156. # end
  157. #
  158. # describe "activity streams" do
  159. # let(:now) { Time.zone.now.to_i }
  160. # let(:activities) do
  161. # [{ action: 'so and so edited their profile', timestamp: now },
  162. # { action: 'so and so uploaded a file', timestamp: (now - 360) }]
  163. # end
  164. # let(:file_activities) do
  165. # [{ action: 'uploaded a file', timestamp: now + 1 }]
  166. # end
  167. #
  168. # before do
  169. # allow(user).to receive(:events).and_return(activities)
  170. # allow(user).to receive(:profile_events).and_return(file_activities)
  171. # end
  172. #
  173. # it "gathers the user's recent activity within the default amount of time" do
  174. # expect(user.all_user_activity).to eq(file_activities.concat(activities))
  175. # end
  176. #
  177. # it "gathers the user's recent activity within a given timestamp" do
  178. # expect(user.all_user_activity(now - 60)).to eq(file_activities.concat([activities.first]))
  179. # end
  180. # end
  181. # describe "proxy_deposit_rights" do
  182. # subject { create :user }
  183. #
  184. # before do
  185. # subject.can_receive_deposits_from << user
  186. # subject.can_make_deposits_for << another_user
  187. # subject.save!
  188. # end
  189. # it "can_receive_deposits_from" do
  190. # expect(subject.can_receive_deposits_from.to_a).to eq [user]
  191. # expect(user.can_make_deposits_for.to_a).to eq [subject]
  192. # end
  193. # it "can_make_deposits_for" do
  194. # expect(subject.can_make_deposits_for.to_a).to eq [another_user]
  195. # expect(another_user.can_receive_deposits_from.to_a).to eq [subject]
  196. # end
  197. # end
  198. # describe "class methods" do
  199. # describe "recent_users" do
  200. # let(:new_users) { described_class.all.order(created_at: :desc) }
  201. #
  202. # before do
  203. # (1..3).each { |i| described_class.create(email: "abc#{i}@blah.frg", password: "blarg1234", created_at: Time.zone.now - i.days) }
  204. # end
  205. #
  206. # context "when has a start date" do
  207. # subject { described_class.recent_users(Time.zone.today - 2.days) }
  208. #
  209. # it "returns valid data" do
  210. # expect(subject.count).to eq 2
  211. # is_expected.to include(new_users[0], new_users[1])
  212. # is_expected.not_to include(new_users[2])
  213. # end
  214. # end
  215. #
  216. # context "when has start and end date" do
  217. # subject { described_class.recent_users(Time.zone.today - 2.days, Time.zone.today - 1.day) }
  218. #
  219. # it "returns valid data" do
  220. # expect(subject.count).to eq 1
  221. # is_expected.to include(new_users[1])
  222. # is_expected.not_to include(new_users[2], new_users[0])
  223. # end
  224. # end
  225. # end
  226. # end
  227. # describe "scope Users" do
  228. # let!(:basic_user) { create(:user) }
  229. # let!(:guest_user) { create(:user, :guest) }
  230. # let!(:audit_user) { User.audit_user }
  231. # let!(:batch_user) { User.batch_user }
  232. #
  233. # context "without_system_accounts" do
  234. # subject { described_class.without_system_accounts }
  235. #
  236. # it "omits audit_user and batch_user" do
  237. # is_expected.to include(basic_user, guest_user)
  238. # is_expected.not_to include(audit_user, batch_user)
  239. # end
  240. # end
  241. # context "registered" do
  242. # subject { described_class.registered }
  243. #
  244. # it "omits guest_user" do
  245. # is_expected.to include(basic_user, audit_user, batch_user)
  246. # is_expected.not_to include(guest_user)
  247. # end
  248. # end
  249. # context "guests" do
  250. # subject { described_class.guests }
  251. #
  252. # it "includes only guest_user" do
  253. # is_expected.not_to include(basic_user, audit_user, batch_user)
  254. # is_expected.to include(guest_user)
  255. # end
  256. # end
  257. # end
  258. end

spec/presenters/hyrax/admin_stats_presenter_spec.rb

100.0% lines covered

52 relevant lines. 52 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'rails_helper'
  3. 1 RSpec.describe Hyrax::AdminStatsPresenter do
  4. 9 let(:stats_filters) { { start_date: start_date, end_date: end_date } }
  5. 3 let(:start_date) { "" }
  6. 4 let(:end_date) { "" }
  7. 9 let(:limit) { 10 }
  8. 9 let(:instance) { described_class.new(stats_filters, limit) }
  9. 1 describe "#valid_dates" do
  10. 1 context "without a start date" do
  11. 1 it "returns true" do
  12. 1 expect(instance.valid_dates).to be true
  13. end
  14. end
  15. 1 context "with a start date (only)" do
  16. 1 context "before/on today" do
  17. 2 let(:start_date) { Date.current.to_s }
  18. 1 it "returns true" do
  19. 1 expect(instance.valid_dates).to be true
  20. end
  21. end
  22. 1 context "after today" do
  23. 2 let(:start_date) { (Date.current + 1).to_s }
  24. 1 it "returns false" do
  25. 1 expect(instance.valid_dates).to be false
  26. end
  27. end
  28. end
  29. 1 context "with an end date" do
  30. 4 let(:end_date) { "2011-11-11" }
  31. 1 context "without a start date" do
  32. 1 it "returns true" do
  33. 1 expect(instance.valid_dates).to be true
  34. end
  35. end
  36. 1 context "after the start date" do
  37. 2 let(:start_date) { "2010-10-10" }
  38. 1 it "returns true" do
  39. 1 expect(instance.valid_dates).to be true
  40. end
  41. end
  42. 1 context "preceding the start date" do
  43. 2 let(:start_date) { "2012-12-12" }
  44. 1 it "returns false" do
  45. 1 expect(instance.valid_dates).to be false
  46. end
  47. end
  48. end
  49. end
  50. 1 describe "#clear_invalid_dates!" do
  51. 1 context "with valid dates" do
  52. 2 let(:start_date) { "2010-10-10" }
  53. 2 let(:end_date) { "2011-11-11" }
  54. 1 it "does not clear filters" do
  55. 1 expect(stats_filters[:start_date]).to be_present
  56. 1 expect(stats_filters[:end_date]).to be_present
  57. 1 instance.clear_invalid_dates!
  58. 1 expect(stats_filters[:start_date]).to be_present
  59. 1 expect(stats_filters[:end_date]).to be_present
  60. end
  61. end
  62. 1 context "with invalid dates" do
  63. 2 let(:start_date) { "2012-12-12" }
  64. 2 let(:end_date) { "2011-11-11" }
  65. 1 it "clears the date values" do
  66. 1 expect(stats_filters[:start_date]).to be_present
  67. 1 expect(stats_filters[:end_date]).to be_present
  68. 1 instance.clear_invalid_dates!
  69. 1 expect(stats_filters[:start_date]).to be_nil
  70. 1 expect(stats_filters[:end_date]).to be_nil
  71. end
  72. end
  73. end
  74. end

spec/presenters/hyrax/data_set_presenter_spec.rb

100.0% lines covered

40 relevant lines. 40 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'rails_helper'
  3. 1 RSpec.describe Hyrax::DataSetPresenter do
  4. 19 subject { described_class.new(double, double) }
  5. 5 let(:solr_document) { SolrDocument.new(attributes) }
  6. 5 let(:request) { double(host: 'example.org', base_url: 'http://example.org') }
  7. 5 let(:user_key) { 'a_user_key' }
  8. 1 let(:attributes) do
  9. 4 { "id" => '888888',
  10. "title_tesim" => ['foo', 'bar'],
  11. "human_readable_type_tesim" => ["Generic Work"],
  12. "has_model_ssim" => ["DataSet"],
  13. "date_created_tesim" => ['an unformatted date'],
  14. "depositor_tesim" => user_key }
  15. end
  16. 5 let(:ability) { double Ability }
  17. 5 let(:presenter) { described_class.new(solr_document, ability, request) }
  18. 2 it { is_expected.to delegate_method(:to_s).to(:solr_document) }
  19. # it { is_expected.to delegate_method(:human_readable_type).to(:solr_document) }
  20. 2 it { is_expected.to delegate_method(:curation_notes_admin).to(:solr_document) }
  21. 2 it { is_expected.to delegate_method(:curation_notes_user).to(:solr_document) }
  22. 2 it { is_expected.to delegate_method(:date_created).to(:solr_document) }
  23. 2 it { is_expected.to delegate_method(:date_modified).to(:solr_document) }
  24. 2 it { is_expected.to delegate_method(:date_published).to(:solr_document) }
  25. 2 it { is_expected.to delegate_method(:date_uploaded).to(:solr_document) }
  26. 2 it { is_expected.to delegate_method(:fundedby).to(:solr_document) }
  27. 2 it { is_expected.to delegate_method(:fundedby_other).to(:solr_document) }
  28. 2 it { is_expected.to delegate_method(:rights_license).to(:solr_document) }
  29. 2 it { is_expected.to delegate_method(:rights_license_other).to(:solr_document) }
  30. 2 it { is_expected.to delegate_method(:based_near_label).to(:solr_document) }
  31. 2 it { is_expected.to delegate_method(:related_url).to(:solr_document) }
  32. 2 it { is_expected.to delegate_method(:depositor).to(:solr_document) }
  33. 2 it { is_expected.to delegate_method(:identifier).to(:solr_document) }
  34. 2 it { is_expected.to delegate_method(:resource_type).to(:solr_document) }
  35. 2 it { is_expected.to delegate_method(:keyword).to(:solr_document) }
  36. 2 it { is_expected.to delegate_method(:itemtype).to(:solr_document) }
  37. 1 describe "#relative_url_root" do
  38. 2 subject { presenter.relative_url_root }
  39. 2 it { is_expected.to eq '' } # this is true for test, in dev or prod it would be equal to '/data'
  40. end
  41. 1 describe "#model_name" do
  42. 2 subject { presenter.model_name }
  43. 2 it { is_expected.to be_kind_of ActiveModel::Name }
  44. end
  45. 1 describe '#manifest_url' do
  46. 2 subject { presenter.manifest_url }
  47. 2 it { is_expected.to eq 'http://example.org/concern/data_sets/888888/manifest' }
  48. end
  49. # describe '#iiif_viewer?' do
  50. # let(:id_present) { false }
  51. # let(:representative_presenter) { double('representative', present?: false) }
  52. # let(:image_boolean) { false }
  53. # let(:iiif_enabled) { false }
  54. # let(:file_set_presenter) { Hyrax::FileSetPresenter.new(solr_document, ability) }
  55. # let(:file_set_presenters) { [file_set_presenter] }
  56. # let(:read_permission) { true }
  57. #
  58. # before do
  59. # allow(presenter).to receive(:representative_id).and_return(id_present)
  60. # allow(presenter).to receive(:representative_presenter).and_return(representative_presenter)
  61. # allow(presenter).to receive(:file_set_presenters).and_return(file_set_presenters)
  62. # allow(file_set_presenter).to receive(:image?).and_return(true)
  63. # allow(ability).to receive(:can?).with(:read, solr_document.id).and_return(read_permission)
  64. # allow(representative_presenter).to receive(:image?).and_return(image_boolean)
  65. # allow(Hyrax.config).to receive(:iiif_image_server?).and_return(iiif_enabled)
  66. # end
  67. #
  68. # subject { presenter.iiif_viewer? }
  69. #
  70. # context 'with no representative_id' do
  71. # it { is_expected.to be false }
  72. # end
  73. #
  74. # context 'with no representative_presenter' do
  75. # let(:id_present) { true }
  76. #
  77. # it { is_expected.to be false }
  78. # end
  79. #
  80. # context 'with non-image representative_presenter' do
  81. # let(:id_present) { true }
  82. # let(:representative_presenter) { double('representative', present?: true) }
  83. # let(:image_boolean) { true }
  84. #
  85. # it { is_expected.to be false }
  86. # end
  87. #
  88. # context 'with IIIF image server turned off' do
  89. # let(:id_present) { true }
  90. # let(:representative_presenter) { double('representative', present?: true) }
  91. # let(:image_boolean) { true }
  92. # let(:iiif_enabled) { false }
  93. #
  94. # it { is_expected.to be false }
  95. # end
  96. #
  97. # context 'with representative image and IIIF turned on' do
  98. # let(:id_present) { true }
  99. # let(:representative_presenter) { double('representative', present?: true) }
  100. # let(:image_boolean) { true }
  101. # let(:iiif_enabled) { true }
  102. #
  103. # it { is_expected.to be true }
  104. #
  105. # context "when the user doesn't have permission to view the image" do
  106. # let(:read_permission) { false }
  107. #
  108. # it { is_expected.to be false }
  109. # end
  110. # end
  111. # end
  112. #
  113. # describe '#stats_path' do
  114. # let(:user) { 'sarah' }
  115. # let(:ability) { double "Ability" }
  116. # let(:work) { build(:generic_work, id: '123abc') }
  117. # let(:attributes) { work.to_solr }
  118. #
  119. # before do
  120. # # https://github.com/samvera/active_fedora/issues/1251
  121. # allow(work).to receive(:persisted?).and_return(true)
  122. # end
  123. #
  124. # it { expect(presenter.stats_path).to eq Hyrax::Engine.routes.url_helpers.stats_work_path(id: work, locale: 'en') }
  125. # end
  126. #
  127. # describe '#itemtype' do
  128. # let(:work) { build(:generic_work, resource_type: type) }
  129. # let(:attributes) { work.to_solr }
  130. # let(:ability) { double "Ability" }
  131. #
  132. # subject { presenter.itemtype }
  133. #
  134. # context 'when resource_type is Audio' do
  135. # let(:type) { ['Audio'] }
  136. #
  137. # it do
  138. # is_expected.to eq 'http://schema.org/AudioObject'
  139. # end
  140. # end
  141. #
  142. # context 'when resource_type is Conference Proceeding' do
  143. # let(:type) { ['Conference Proceeding'] }
  144. #
  145. # it { is_expected.to eq 'http://schema.org/ScholarlyArticle' }
  146. # end
  147. # end
  148. #
  149. # describe 'admin users' do
  150. # let(:user) { create(:user) }
  151. # let(:ability) { Ability.new(user) }
  152. # let(:attributes) do
  153. # {
  154. # "read_access_group_ssim" => ["public"],
  155. # 'id' => '99999'
  156. # }
  157. # end
  158. #
  159. # before { allow(user).to receive_messages(groups: ['admin', 'registered']) }
  160. #
  161. # context 'with a new public work' do
  162. # it 'can feature the work' do
  163. # allow(user).to receive(:can?).with(:create, FeaturedWork).and_return(true)
  164. # expect(presenter.work_featurable?).to be true
  165. # expect(presenter.display_feature_link?).to be true
  166. # expect(presenter.display_unfeature_link?).to be false
  167. # end
  168. # end
  169. #
  170. # context 'with a featured work' do
  171. # before { FeaturedWork.create(work_id: attributes.fetch('id')) }
  172. # it 'can unfeature the work' do
  173. # expect(presenter.work_featurable?).to be true
  174. # expect(presenter.display_feature_link?).to be false
  175. # expect(presenter.display_unfeature_link?).to be true
  176. # end
  177. # end
  178. #
  179. # describe "#editor?" do
  180. # subject { presenter.editor? }
  181. #
  182. # it { is_expected.to be true }
  183. # end
  184. # end
  185. #
  186. # describe '#tweeter' do
  187. # let(:user) { instance_double(User, user_key: 'user_key') }
  188. #
  189. # subject { presenter.tweeter }
  190. #
  191. # it 'delegates the depositor as the user_key to TwitterPresenter.twitter_handle_for' do
  192. # expect(Hyrax::TwitterPresenter).to receive(:twitter_handle_for).with(user_key: user_key)
  193. # subject
  194. # end
  195. # end
  196. #
  197. # describe "#permission_badge" do
  198. # let(:badge) { instance_double(Hyrax::PermissionBadge) }
  199. #
  200. # before do
  201. # allow(Hyrax::PermissionBadge).to receive(:new).and_return(badge)
  202. # end
  203. # it "calls the PermissionBadge object" do
  204. # expect(badge).to receive(:render)
  205. # presenter.permission_badge
  206. # end
  207. # end
  208. #
  209. # describe "#work_presenters" do
  210. # let(:obj) { create(:work_with_file_and_work) }
  211. # let(:attributes) { obj.to_solr }
  212. #
  213. # it "filters out members that are file sets" do
  214. # expect(presenter.work_presenters.size).to eq 1
  215. # expect(presenter.work_presenters.first).to be_instance_of(described_class)
  216. # end
  217. # end
  218. #
  219. # describe "#member_presenters" do
  220. # let(:obj) { create(:work_with_file_and_work) }
  221. # let(:attributes) { obj.to_solr }
  222. #
  223. # it "returns appropriate classes for each" do
  224. # expect(presenter.member_presenters.size).to eq 2
  225. # expect(presenter.member_presenters.first).to be_instance_of(Hyrax::FileSetPresenter)
  226. # expect(presenter.member_presenters.last).to be_instance_of(described_class)
  227. # end
  228. # end
  229. #
  230. # describe "#file_set_presenters" do
  231. # let(:obj) { create(:work_with_ordered_files) }
  232. # let(:attributes) { obj.to_solr }
  233. #
  234. # it "displays them in order" do
  235. # expect(presenter.file_set_presenters.map(&:id)).to eq obj.ordered_member_ids
  236. # end
  237. #
  238. # context "solr query" do
  239. # before do
  240. # expect(ActiveFedora::SolrService).to receive(:query).twice.with(anything, hash_including(rows: 10_000)).and_return([])
  241. # end
  242. #
  243. # it "requests >10 rows" do
  244. # presenter.file_set_presenters
  245. # end
  246. # end
  247. #
  248. # context "when some of the members are not file sets" do
  249. # let(:another_work) { create(:work) }
  250. #
  251. # before do
  252. # obj.ordered_members << another_work
  253. # obj.save!
  254. # end
  255. #
  256. # it "filters out members that are not file sets" do
  257. # expect(presenter.file_set_presenters.map(&:id)).not_to include another_work.id
  258. # end
  259. # end
  260. # end
  261. #
  262. # describe "#representative_presenter" do
  263. # let(:obj) { create(:work_with_representative_file) }
  264. # let(:attributes) { obj.to_solr }
  265. #
  266. # it "has a representative" do
  267. # expect(Hyrax::PresenterFactory).to receive(:build_for)
  268. # .with(ids: [obj.members[0].id],
  269. # presenter_class: Hyrax::CompositePresenterFactory,
  270. # presenter_args: [ability, request])
  271. # .and_return ["abc"]
  272. # expect(presenter.representative_presenter).to eq("abc")
  273. # end
  274. #
  275. # context 'without a representative' do
  276. # let(:obj) { create(:work) }
  277. #
  278. # it 'has a nil presenter' do
  279. # expect(presenter.representative_presenter).to be_nil
  280. # end
  281. # end
  282. #
  283. # context 'when it is its own representative' do
  284. # let(:obj) { create(:work) }
  285. #
  286. # before do
  287. # obj.representative_id = obj.id
  288. # obj.save
  289. # end
  290. #
  291. # it 'has a nil presenter; avoids infinite loop' do
  292. # expect(presenter.representative_presenter).to be_nil
  293. # end
  294. # end
  295. # end
  296. #
  297. # describe "#download_url" do
  298. # subject { presenter.download_url }
  299. #
  300. # let(:solr_document) { SolrDocument.new(work.to_solr) }
  301. #
  302. # context "with a representative" do
  303. # let(:work) { create(:work_with_representative_file) }
  304. #
  305. # it { is_expected.to eq "http://#{request.host}/downloads/#{work.representative_id}" }
  306. # end
  307. #
  308. # context "without a representative" do
  309. # let(:work) { create(:work) }
  310. #
  311. # it { is_expected.to eq '' }
  312. # end
  313. # end
  314. 1 describe '#page_title' do
  315. 2 subject { presenter.page_title }
  316. 2 it { is_expected.to eq 'Data Set | foo | ID: 888888 | DataCORE' }
  317. end
  318. # describe "#valid_child_concerns" do
  319. # subject { presenter }
  320. #
  321. # it "delegates to the class attribute of the model" do
  322. # allow(DataSet).to receive(:valid_child_concerns).and_return([DataSet])
  323. #
  324. # expect(subject.valid_child_concerns).to eq [DataSet]
  325. # end
  326. # end
  327. #
  328. # describe "#attribute_to_html" do
  329. # let(:renderer) { double('renderer') }
  330. #
  331. # context 'with an existing field' do
  332. # before do
  333. # allow(Hyrax::Renderers::AttributeRenderer).to receive(:new)
  334. # .with(:title, ['foo', 'bar'], {})
  335. # .and_return(renderer)
  336. # end
  337. #
  338. # it "calls the AttributeRenderer" do
  339. # expect(renderer).to receive(:render)
  340. # presenter.attribute_to_html(:title)
  341. # end
  342. # end
  343. #
  344. # context "with a field that doesn't exist" do
  345. # it "logs a warning" do
  346. # expect(Rails.logger).to receive(:warn).with('Hyrax::WorkShowPresenter attempted to render restrictions, but no method exists with that name.')
  347. # presenter.attribute_to_html(:restrictions)
  348. # end
  349. # end
  350. # end
  351. #
  352. # context "with workflow" do
  353. # let(:user) { create(:user) }
  354. # let(:ability) { Ability.new(user) }
  355. # let(:entity) { instance_double(Sipity::Entity) }
  356. #
  357. # describe "#workflow" do
  358. # subject { presenter.workflow }
  359. #
  360. # it { is_expected.to be_kind_of Hyrax::WorkflowPresenter }
  361. # end
  362. # end
  363. #
  364. # context "with inspect_work" do
  365. # let(:user) { create(:user) }
  366. # let(:ability) { Ability.new(user) }
  367. #
  368. # describe "#inspect_work" do
  369. # subject { presenter.inspect_work }
  370. #
  371. # it { is_expected.to be_kind_of Hyrax::InspectWorkPresenter }
  372. # end
  373. # end
  374. #
  375. # describe "graph export methods" do
  376. # let(:graph) do
  377. # RDF::Graph.new.tap do |g|
  378. # g << [RDF::URI('http://example.com/1'), RDF::Vocab::DC.title, 'Test title']
  379. # end
  380. # end
  381. #
  382. # let(:exporter) { double }
  383. #
  384. # before do
  385. # allow(Hyrax::GraphExporter).to receive(:new).and_return(exporter)
  386. # allow(exporter).to receive(:fetch).and_return(graph)
  387. # end
  388. #
  389. # describe "#export_as_nt" do
  390. # subject { presenter.export_as_nt }
  391. #
  392. # it { is_expected.to eq "<http://example.com/1> <http://purl.org/dc/terms/title> \"Test title\" .\n" }
  393. # end
  394. #
  395. # describe "#export_as_ttl" do
  396. # subject { presenter.export_as_ttl }
  397. #
  398. # it { is_expected.to eq "\n<http://example.com/1> <http://purl.org/dc/terms/title> \"Test title\" .\n" }
  399. # end
  400. #
  401. # describe "#export_as_jsonld" do
  402. # subject { presenter.export_as_jsonld }
  403. #
  404. # it do
  405. # is_expected.to eq '{
  406. # "@context": {
  407. # "dc": "http://purl.org/dc/terms/"
  408. # },
  409. # "@id": "http://example.com/1",
  410. # "dc:title": "Test title"
  411. # }'
  412. # end
  413. # end
  414. # end
  415. #
  416. # describe "#manifest" do
  417. # let(:work) { create(:work_with_one_file) }
  418. # let(:solr_document) { SolrDocument.new(work.to_solr) }
  419. #
  420. # describe "#sequence_rendering" do
  421. # subject do
  422. # presenter.sequence_rendering
  423. # end
  424. #
  425. # before do
  426. # Hydra::Works::AddFileToFileSet.call(work.file_sets.first,
  427. # File.open(fixture_path + '/world.png'), :original_file)
  428. # end
  429. #
  430. # it "returns a hash containing the rendering information" do
  431. # work.rendering_ids = [work.file_sets.first.id]
  432. # expect(subject).to be_an Array
  433. # end
  434. # end
  435. #
  436. # describe "#manifest_metadata" do
  437. # subject do
  438. # presenter.manifest_metadata
  439. # end
  440. #
  441. # before do
  442. # work.title = ['Test title', 'Another test title']
  443. # end
  444. #
  445. # it "returns an array of metadata values" do
  446. # expect(subject[0]['label']).to eq('Title')
  447. # expect(subject[0]['value']).to include('Test title', 'Another test title')
  448. # end
  449. # end
  450. # end
  451. end

spec/presenters/hyrax/dissertation_presenter_spec.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work Dissertation`
  3. 1 require 'rails_helper'
  4. 1 RSpec.describe Hyrax::DissertationPresenter do
  5. 1 it "has tests" do
  6. 1 skip "Add your tests here"
  7. end
  8. end

spec/presenters/hyrax/generic_work_presenter_spec.rb

100.0% lines covered

4 relevant lines. 4 lines covered and 0 lines missed.
    
  1. # Generated via
  2. # `rails generate hyrax:work GenericWork`
  3. 1 require 'rails_helper'
  4. 1 RSpec.describe Hyrax::GenericWorkPresenter do
  5. 1 it "has tests" do
  6. 1 skip "Add your tests here"
  7. end
  8. end

spec/rails_helper.rb

100.0% lines covered

23 relevant lines. 23 lines covered and 0 lines missed.
    
  1. # This file is copied to spec/ when you run 'rails generate rspec:install'
  2. 1 require 'spec_helper'
  3. 1 ENV['RAILS_ENV'] ||= 'test'
  4. 1 require File.expand_path('../../config/environment', __FILE__)
  5. # Prevent database truncation if the environment is production
  6. 1 abort("The Rails environment is running in production mode!") if Rails.env.production?
  7. 1 require 'rspec/rails'
  8. # Add additional requires below this line. Rails is not loaded until this point!
  9. # Requires supporting ruby files with custom matchers and macros, etc, in
  10. # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
  11. # run as spec files by default. This means that files in spec/support that end
  12. # in _spec.rb will both be required and run as specs, causing the specs to be
  13. # run twice. It is recommended that you do not name files matching this glob to
  14. # end with _spec.rb. You can configure this pattern with the --pattern
  15. # option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
  16. #
  17. # The following line is provided for convenience purposes. It has the downside
  18. # of increasing the boot-up time by auto-requiring all files in the support
  19. # directory. Alternatively, in the individual `*_spec.rb` files, manually
  20. # require only the support files necessary.
  21. #
  22. 3 Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } # rubocop:disable Rails/FilePath
  23. # Checks for pending migrations and applies them before tests are run.
  24. # If you are not using ActiveRecord, you can remove this line.
  25. 1 ActiveRecord::Migration.maintain_test_schema!
  26. 1 RSpec.configure do |config|
  27. # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  28. 1 config.fixture_path = "#{::Rails.root}/spec/fixtures"
  29. # If you're not using ActiveRecord, or you'd prefer not to run each of your
  30. # examples within a transaction, remove the following line or assign false
  31. # instead of true.
  32. 1 config.use_transactional_fixtures = false # true
  33. # RSpec Rails can automatically mix in different behaviours to your tests
  34. # based on their file location, for example enabling you to call `get` and
  35. # `post` in specs under `spec/controllers`.
  36. #
  37. # You can disable this behaviour by removing the line below, and instead
  38. # explicitly tag your specs with their type, e.g.:
  39. #
  40. # RSpec.describe UsersController, :type => :controller do
  41. # # ...
  42. # end
  43. #
  44. # The different available types are documented in the features, such as in
  45. # https://relishapp.com/rspec/rspec-rails/docs
  46. 1 config.infer_spec_type_from_file_location!
  47. # Filter lines from Rails gems in backtraces.
  48. 1 config.filter_rails_from_backtrace!
  49. # arbitrary gems may also be filtered via:
  50. # config.filter_gems_from_backtrace("gem name")
  51. 1 config.include Devise::Test::ControllerHelpers, type: :controller
  52. 1 config.before(:suite) do
  53. 1 DatabaseCleaner.clean_with(:truncation)
  54. end
  55. 1 config.before do
  56. 410 DatabaseCleaner.strategy = :transaction
  57. end
  58. 1 config.before(:each, js: true) do
  59. 2 DatabaseCleaner.strategy = :truncation
  60. end
  61. # This block must be here, do not combine with the other `before(:each)` block.
  62. # This makes it so Capybara can see the database.
  63. 1 config.before do
  64. 410 DatabaseCleaner.start
  65. end
  66. 1 config.after do
  67. 410 DatabaseCleaner.clean
  68. end
  69. end

spec/services/dataset/date_coverage_service_spec.rb

100.0% lines covered

42 relevant lines. 42 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe Dataset::DateCoverageService do
  3. 1 describe '#params_to_interval' do
  4. 1 context "when called with year, month, and day for begin_date and end_date" do
  5. 1 it "returns interval with day precision" do
  6. 1 params = { :date_coverage_begin_year => "2001", :date_coverage_begin_month => "1", :date_coverage_begin_day => "5",
  7. :date_coverage_end_year => "2001", :date_coverage_end_month => "1", :date_coverage_end_day => "10" }
  8. 1 expect(Dataset::DateCoverageService.params_to_interval params).to eq Date.edtf('2001-01-05/2001-01-10')
  9. end
  10. end
  11. 1 context "when called with year and month for begin_date and end_date" do
  12. 1 it "returns interval with month precision" do
  13. 1 params = { :date_coverage_begin_year => "2001", :date_coverage_begin_month => "1", :date_coverage_begin_day => "",
  14. :date_coverage_end_year => "2001", :date_coverage_end_month => "2", :date_coverage_end_day => "" }
  15. 1 expect(Dataset::DateCoverageService.params_to_interval params).to eq Date.edtf('2001-01/2001-02')
  16. end
  17. end
  18. 1 context "when called with year begin_date and end_date" do
  19. 1 it "returns interval with year precision" do
  20. 1 params = { :date_coverage_begin_year => "2002", :date_coverage_begin_month => "", :date_coverage_begin_day => "",
  21. :date_coverage_end_year => "2003", :date_coverage_end_month => "", :date_coverage_end_day => "" }
  22. 1 expect(Dataset::DateCoverageService.params_to_interval params).to eq Date.edtf('2002/2003')
  23. end
  24. end
  25. 1 context "when called with begin_date but no end_date" do
  26. 1 it "returns Start Date" do
  27. 1 params = { :date_coverage_begin_year => "2007", :date_coverage_begin_month => "5", :date_coverage_begin_day => "6",
  28. :date_coverage_end_year => "", :date_coverage_end_month => "", :date_coverage_end_day => "" }
  29. 1 expect(Dataset::DateCoverageService.params_to_interval params).to eq Date.edtf('2007-05-06')
  30. end
  31. end
  32. 1 context "when called with end_date but no begin_date" do
  33. 1 it "returns unknown to End Date" do
  34. 1 params = { :date_coverage_begin_year => "", :date_coverage_begin_month => "", :date_coverage_begin_day => "",
  35. :date_coverage_end_year => "2010", :date_coverage_end_month => "10", :date_coverage_end_day => "10" }
  36. 1 expect(Dataset::DateCoverageService.params_to_interval params).to eq Date.edtf('unknown/2010-10-10')
  37. end
  38. end
  39. 1 context "when called with no date values" do
  40. 1 it "returns blank " do
  41. 1 params = { :date_coverage_begin_year => "", :date_coverage_begin_month => "", :date_coverage_begin_day => "",
  42. :date_coverage_end_year => "", :date_coverage_end_month => "", :date_coverage_end_day => "" }
  43. 1 expect(Dataset::DateCoverageService.params_to_interval(params)).to be_blank
  44. end
  45. end
  46. 1 context "when called with reversed date values" do
  47. 1 it "returns blank" do
  48. 1 params = { :date_coverage_begin_year => "2001", :date_coverage_begin_month => "1", :date_coverage_begin_day => "6",
  49. :date_coverage_end_year => "2001", :date_coverage_end_month => "1", :date_coverage_end_day => "5" }
  50. 1 expect(Dataset::DateCoverageService.params_to_interval(params)).to be_blank
  51. end
  52. end
  53. end
  54. 1 describe '#interval_to_params' do
  55. 1 context "when called with an interval" do
  56. 1 it "returns date params of interval" do
  57. 1 params = { :date_coverage_begin_year => "2002", :date_coverage_begin_month => "2", :date_coverage_begin_day => "6",
  58. :date_coverage_end_year => "2004", :date_coverage_end_month => "8", :date_coverage_end_day => "16" }
  59. 1 expect(Dataset::DateCoverageService.interval_to_params Date.edtf('2002-02-06/2004-08-16')).to eq params
  60. end
  61. end
  62. 1 context "when called with argument that is not an interval" do
  63. 1 it "returns blank when not called with interval" do
  64. 1 expect(Dataset::DateCoverageService.interval_to_params Date.new(2001,2,25) ).to be_blank
  65. end
  66. end
  67. 1 context "when called with interval in reverse chronological order" do
  68. 1 it "returns blank" do
  69. 1 expect(Dataset::DateCoverageService.interval_to_params Date.edtf('2004-08-16/2002-02-06') ).to be_blank
  70. end
  71. end
  72. end
  73. end

spec/services/deepblue/about_to_expire_embargoes_service_spec.rb

100.0% lines covered

159 relevant lines. 159 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 class MockAsset
  3. 1 def initialize( id:, model_name: )
  4. 5 @id = id
  5. 5 @model_name = model_name
  6. end
  7. 1 def id
  8. 5 @id.to_s
  9. end
  10. 1 def model_name
  11. 2 @model_name
  12. end
  13. 1 def to_ary
  14. 3 [self]
  15. end
  16. end
  17. 1 class MockLeadTime
  18. 1 def initialize(days:)
  19. 5 @days = days
  20. end
  21. 1 def to_s
  22. 5 @days.to_s + " days"
  23. end
  24. 1 def days
  25. 5 @days
  26. end
  27. end
  28. 1 RSpec.describe Deepblue::AboutToExpireEmbargoesService do
  29. 12 subject { described_class.new }
  30. 1 describe "#initialize" do
  31. 1 before {
  32. 2 allow(Deepblue::LoggingHelper).to receive(:here).and_return "here"
  33. 2 allow(Deepblue::LoggingHelper).to receive(:called_from).and_return "from"
  34. 2 allow(Deepblue::LoggingHelper).to receive(:obj_class).with("class", anything).and_return "object class"
  35. 2 allow(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  36. "from",
  37. "object class",
  38. "email_owner=true",
  39. "expiration_lead_days=",
  40. "skip_file_sets=true",
  41. "test_mode=true",
  42. "to_console=false",
  43. "verbose=false",
  44. ""]
  45. }
  46. 1 it "calls LoggingHelper.bold_debug" do
  47. 1 expect(Deepblue::LoggingHelper).to receive(:here).and_return "here"
  48. 1 expect(Deepblue::LoggingHelper).to receive(:called_from).and_return "from"
  49. 1 expect(Deepblue::LoggingHelper).to receive(:obj_class).with("class", anything).and_return "object class"
  50. 1 expect(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  51. "from",
  52. "object class",
  53. "email_owner=true",
  54. "expiration_lead_days=",
  55. "skip_file_sets=true",
  56. "test_mode=true",
  57. "to_console=false",
  58. "verbose=false",
  59. ""]
  60. 1 Deepblue::AboutToExpireEmbargoesService.new
  61. end
  62. 1 it "sets instance variables" do
  63. 1 subject.instance_variable_get(:@email_owner) == true
  64. 1 subject.instance_variable_get(:@expiration_lead_days) == nil
  65. 1 subject.instance_variable_get(:@skip_file_sets) == true
  66. 1 subject.instance_variable_get(:@test_mode) == true
  67. 1 subject.instance_variable_get(:@to_console) == false
  68. 1 subject.instance_variable_get(:@verbose) == false
  69. end
  70. end
  71. 1 describe "#run" do
  72. 1 mock_asset = MockAsset.new id:1001, model_name: "model name"
  73. 1 before {
  74. # stubbing initialize
  75. 3 allow(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  76. "from",
  77. "object class",
  78. "email_owner=true",
  79. "expiration_lead_days=",
  80. "skip_file_sets=true",
  81. "test_mode=true",
  82. "to_console=false",
  83. "verbose=false",
  84. ""]
  85. 3 allow(Deepblue::LoggingHelper).to receive(:here).and_return "here"
  86. 3 allow(Deepblue::LoggingHelper).to receive(:called_from).and_return "from"
  87. 3 allow(Deepblue::LoggingHelper).to receive(:obj_class).with("class", anything).and_return "object class"
  88. 3 allow(DateTime).to receive(:now).and_return DateTime.new(2025, 5, 5)
  89. 3 allow(subject).to receive(:assets_under_embargo).and_return(mock_asset)
  90. 3 allow(subject).to receive(:about_to_expire_embargoes_for_lead_days).with lead_days: 7
  91. 3 allow(subject).to receive(:about_to_expire_embargoes_for_lead_days).with lead_days: 1
  92. }
  93. 1 context "when @expiration_lead_days is blank" do
  94. 1 it "calls LoggingHelper.bold_debug, calls about_to_expire_embargoes_for_lead_days with default values" do
  95. 1 expect(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  96. "from",
  97. "object class",
  98. "@email_owner=true",
  99. "@expiration_lead_days=",
  100. "@skip_file_sets=true",
  101. "@test_mode=true",
  102. "@to_console=false",
  103. "@verbose=false",
  104. ""]
  105. 1 expect(subject).to receive(:about_to_expire_embargoes_for_lead_days).with lead_days: 7
  106. 1 expect(subject).to receive(:about_to_expire_embargoes_for_lead_days).with lead_days: 1
  107. 1 subject.run
  108. 1 subject.instance_variable_get(:@now) == DateTime.new(2025, 5, 5)
  109. 1 subject.instance_variable_get(:@assets) == [mock_asset]
  110. end
  111. end
  112. 1 context "when @expiration_lead_days is an integer greater than zero" do
  113. 1 before {
  114. 1 subject.instance_variable_set(:@expiration_lead_days, "27")
  115. 1 allow(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  116. "from",
  117. "object class",
  118. "@email_owner=true",
  119. "@expiration_lead_days=27",
  120. "@skip_file_sets=true",
  121. "@test_mode=true",
  122. "@to_console=false",
  123. "@verbose=false",
  124. ""]
  125. 1 allow(subject).to receive(:about_to_expire_embargoes_for_lead_days).with lead_days: 27
  126. }
  127. 1 it "calls LoggingHelper.bold_debug, calls about_to_expire_embargoes_for_lead_days with @expiration_lead_days" do
  128. 1 expect(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  129. "from",
  130. "object class",
  131. "@email_owner=true",
  132. "@expiration_lead_days=27",
  133. "@skip_file_sets=true",
  134. "@test_mode=true",
  135. "@to_console=false",
  136. "@verbose=false",
  137. ""]
  138. 1 expect(subject).to receive(:about_to_expire_embargoes_for_lead_days).with lead_days: 27
  139. 1 subject.run
  140. end
  141. end
  142. 1 context "when @expiration_lead_days is 0 or less" do
  143. 1 before {
  144. 1 subject.instance_variable_set(:@expiration_lead_days, "0")
  145. 1 allow(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  146. "from",
  147. "object class",
  148. "@email_owner=true",
  149. "@expiration_lead_days=0",
  150. "@skip_file_sets=true",
  151. "@test_mode=true",
  152. "@to_console=false",
  153. "@verbose=false",
  154. ""]
  155. }
  156. 1 it "calls LoggingHelper.bold_debug, calls about_to_expire_embargoes_for_lead_days with default values" do
  157. 1 expect(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  158. "from",
  159. "object class",
  160. "@email_owner=true",
  161. "@expiration_lead_days=0",
  162. "@skip_file_sets=true",
  163. "@test_mode=true",
  164. "@to_console=false",
  165. "@verbose=false",
  166. ""]
  167. 1 expect(subject).to receive(:about_to_expire_embargoes_for_lead_days).with lead_days: 7
  168. 1 expect(subject).to receive(:about_to_expire_embargoes_for_lead_days).with lead_days: 1
  169. 1 subject.run
  170. end
  171. end
  172. end
  173. 1 describe "#about_to_expire_embargoes_for_lead_days" do
  174. 1 before {
  175. 5 allow(subject).to receive(:run_msg).with "about_to_expire_embargoes_for_lead_days: lead_days=21 days"
  176. 5 subject.instance_variable_set(:@now, DateTime.new(2025, 2, 2))
  177. 5 allow(subject).to receive(:run_msg).with "lead_date=20250202"
  178. 5 allow(subject).to receive(:run_msg).with "1001 embargo_release_date=20250303"
  179. 5 subject.instance_variable_set(:@email_owner, "email owner")
  180. 5 subject.instance_variable_set(:@test_mode, "test mode")
  181. 5 subject.instance_variable_set(:@verbose, "verbose")
  182. }
  183. 1 context "when @skip_file_sets is true and asset.model_name is 'FileSet'" do
  184. 1 before {
  185. 1 subject.instance_variable_set(:@skip_file_sets, true)
  186. 1 asset = MockAsset.new(id: 1001, model_name: "FileSet")
  187. 1 subject.instance_variable_set(:@assets, [asset])
  188. 1 allow(subject).to receive(:asset_embargo_release_date).with(asset: asset).and_return DateTime.new(2025, 3, 3)
  189. }
  190. 1 it "skips loop through @assets " do
  191. 1 expect(subject).to receive(:run_msg).with "about_to_expire_embargoes_for_lead_days: lead_days=21 days"
  192. 1 expect(subject).to receive(:run_msg).with "lead_date=20250223"
  193. 1 subject.about_to_expire_embargoes_for_lead_days lead_days: MockLeadTime.new(days: 21)
  194. end
  195. end
  196. 1 context "when @skip_file_sets is false and asset.model_name is 'FileSet'" do
  197. 1 before {
  198. 1 subject.instance_variable_set(:@skip_file_sets, false)
  199. 1 asset = MockAsset.new(id: 1001, model_name: "FileSet")
  200. 1 subject.instance_variable_set(:@assets, [asset])
  201. 1 allow(subject).to receive(:asset_embargo_release_date).with(asset: asset).and_return DateTime.new(2025, 3, 3)
  202. }
  203. 1 it "outputs embargo_release_date" do
  204. 1 expect(subject).to receive(:run_msg).with "about_to_expire_embargoes_for_lead_days: lead_days=21 days"
  205. 1 expect(subject).to receive(:run_msg).with "lead_date=20250223"
  206. 1 expect(subject).to receive(:run_msg).with "1001 embargo_release_date=20250303"
  207. 1 subject.about_to_expire_embargoes_for_lead_days lead_days: MockLeadTime.new(days: 21)
  208. end
  209. end
  210. 1 context "when @skip_file_sets is true and asset.model_name is not 'FileSet'" do
  211. 1 before {
  212. 1 subject.instance_variable_set(:@skip_file_sets, true)
  213. 1 asset = MockAsset.new(id: 1001, model_name: "model name")
  214. 1 subject.instance_variable_set(:@assets, [asset])
  215. 1 allow(subject).to receive(:asset_embargo_release_date).with(asset: asset).and_return DateTime.new(2025, 3, 3)
  216. }
  217. 1 it "outputs embargo_release_date" do
  218. 1 expect(subject).to receive(:run_msg).with "about_to_expire_embargoes_for_lead_days: lead_days=21 days"
  219. 1 expect(subject).to receive(:run_msg).with "lead_date=20250223"
  220. 1 expect(subject).to receive(:run_msg).with "1001 embargo_release_date=20250303"
  221. 1 subject.about_to_expire_embargoes_for_lead_days lead_days: MockLeadTime.new(days: 21)
  222. end
  223. end
  224. 1 context "when embargo_release_date equals lead_date" do
  225. 1 asset = MockAsset.new(id: 1001, model_name: "model name")
  226. 1 before {
  227. 2 subject.instance_variable_set(:@skip_file_sets, false)
  228. 2 subject.instance_variable_set(:@assets, [asset])
  229. 2 allow(subject).to receive(:asset_embargo_release_date).with(asset: asset).and_return DateTime.new(2025, 2, 23)
  230. }
  231. 1 context "when @test_mode is false" do
  232. 1 mockLeadTime = MockLeadTime.new(days: 21)
  233. 1 before {
  234. 1 subject.instance_variable_set(:@test_mode, false)
  235. 1 allow(subject).to receive(:about_to_expire_embargo_email).with( asset: asset,
  236. expiration_days: mockLeadTime,
  237. email_owner: "email owner",
  238. test_mode: false,
  239. verbose: "verbose" )
  240. }
  241. 1 it "calls about_to_expire_embargo_email" do
  242. 1 expect(subject).to receive(:run_msg).with "about_to_expire_embargoes_for_lead_days: lead_days=21 days"
  243. 1 expect(subject).to receive(:run_msg).with "lead_date=20250223"
  244. 1 expect(subject).to receive(:run_msg).with "1001 embargo_release_date=20250223"
  245. 1 expect(subject).to receive(:about_to_expire_embargo_email).with( asset: asset,
  246. expiration_days: mockLeadTime,
  247. email_owner: "email owner",
  248. test_mode: false,
  249. verbose: "verbose" )
  250. 1 subject.about_to_expire_embargoes_for_lead_days lead_days: mockLeadTime
  251. end
  252. end
  253. 1 context "when @test_mode is true" do
  254. 1 before {
  255. 1 subject.instance_variable_set(:@test_mode, true)
  256. }
  257. 1 it "outputs message" do
  258. 1 expect(subject).to receive(:run_msg).with "about_to_expire_embargoes_for_lead_days: lead_days=21 days"
  259. 1 expect(subject).to receive(:run_msg).with "lead_date=20250223"
  260. 1 expect(subject).to receive(:run_msg).with "1001 embargo_release_date=20250223"
  261. 1 expect(subject).to receive(:run_msg).with "about to call about_to_expire_embargo_email for asset 1001"
  262. 1 subject.about_to_expire_embargoes_for_lead_days lead_days: MockLeadTime.new(days: 21)
  263. end
  264. end
  265. end
  266. end
  267. 1 describe "#run_msg" do
  268. 1 before {
  269. 2 allow(Deepblue::LoggingHelper).to receive(:debug).with "message"
  270. }
  271. 1 context "when @to_console is false" do
  272. 1 before {
  273. 1 subject.instance_variable_set(:@to_console, false)
  274. }
  275. 1 it "calls LoggingHelper.debug" do
  276. 1 expect(Deepblue::LoggingHelper).to receive(:debug).with "message"
  277. 1 subject.run_msg "message"
  278. end
  279. end
  280. 1 context "when @to_console is true" do
  281. 1 before {
  282. 1 subject.instance_variable_set(:@to_console, true)
  283. }
  284. 1 it "calls LoggingHelper.debug" do
  285. 1 expect(Deepblue::LoggingHelper).to receive(:debug).with "message"
  286. 1 expect(subject).to receive(:puts).with("message")
  287. 1 subject.run_msg "message"
  288. end
  289. end
  290. end
  291. end

spec/services/deepblue/deactivate_expired_embargoes_service_spec.rb

100.0% lines covered

109 relevant lines. 109 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 class MockExpiredAsset
  3. 1 def initialize (model_name: "FileSet")
  4. 2 @model_name = model_name
  5. end
  6. 1 def to_ary
  7. 3 [self]
  8. end
  9. 1 def model_name
  10. 3 @model_name
  11. end
  12. 1 def id
  13. 3 "101"
  14. end
  15. 1 def human_readable_type
  16. 1 "typographic"
  17. end
  18. 1 def solr_document
  19. 1 OpenStruct.new(title: 'solaris')
  20. end
  21. 1 def embargo_release_date
  22. 1 "April 2nd 2025"
  23. end
  24. 1 def visibility_after_embargo
  25. 1 "sparkling clear"
  26. end
  27. end
  28. 1 RSpec.describe Deepblue::DeactivateExpiredEmbargoesService do
  29. 1 describe "#initialize" do
  30. 2 subject { described_class.new( email_owner: false, skip_file_sets: false, test_mode: false, to_console: true, verbose: true) }
  31. 1 before {
  32. 1 allow(Deepblue::LoggingHelper).to receive(:here).and_return "here"
  33. 1 allow(Deepblue::LoggingHelper).to receive(:called_from).and_return "from"
  34. 1 allow(Deepblue::LoggingHelper).to receive(:obj_class).with("class", anything).and_return "object class"
  35. 1 allow(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  36. "from",
  37. "object class",
  38. "email_owner=false",
  39. "skip_file_sets=false",
  40. "test_mode=false",
  41. "to_console=true",
  42. "verbose=true",
  43. ""]
  44. }
  45. 1 it "calls LoggingHelper.bold_debug" do
  46. 1 expect(Deepblue::LoggingHelper).to receive(:here).and_return "here"
  47. 1 expect(Deepblue::LoggingHelper).to receive(:called_from).and_return "from"
  48. 1 expect(Deepblue::LoggingHelper).to receive(:obj_class).with("class", anything).and_return "object class"
  49. 1 expect(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  50. "from",
  51. "object class",
  52. "email_owner=false",
  53. "skip_file_sets=false",
  54. "test_mode=false",
  55. "to_console=true",
  56. "verbose=true",
  57. ""]
  58. 1 subject.instance_variable_get(:@email_owner) == false
  59. 1 subject.instance_variable_get(:@skip_file_sets) == false
  60. 1 subject.instance_variable_get(:@test_mode) == false
  61. 1 subject.instance_variable_get(:@to_console) == true
  62. 1 subject.instance_variable_get(:@verbose) == true
  63. end
  64. end
  65. 1 describe "#run" do
  66. 1 mock_asset = MockExpiredAsset.new
  67. 1 before {
  68. 3 allow(Deepblue::LoggingHelper).to receive(:here).and_return "here"
  69. 3 allow(Deepblue::LoggingHelper).to receive(:called_from).and_return "from"
  70. 3 allow(Deepblue::LoggingHelper).to receive(:obj_class).with("class", anything).and_return "object class"
  71. 3 allow(DateTime).to receive(:now).and_return DateTime.new(2025, 6, 1)
  72. 3 allow(Hyrax::EmbargoService).to receive(:assets_with_expired_embargoes).and_return(mock_asset)
  73. 3 allow(subject).to receive(:run_msg).with "The number of assets with expired embargoes is: 1"
  74. }
  75. 1 context "when verbose is false and asset.model_name is not 'FileSet'" do
  76. 1 mock_asset_2 = MockExpiredAsset.new(model_name: "Work")
  77. 2 subject { described_class.new( skip_file_sets: true, verbose: false) }
  78. 1 before {
  79. 1 allow(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  80. "from",
  81. ""]
  82. 1 allow(Hyrax::EmbargoService).to receive(:assets_with_expired_embargoes).and_return(mock_asset_2)
  83. 1 allow(::ActiveFedora::Base).to receive(:find).with("101").and_return "basic"
  84. 1 allow(Deepblue::ProvenanceHelper).to receive(:system_as_current_user).and_return "au courant"
  85. 1 allow(subject).to receive(:deactivate_embargo).with(curation_concern: "basic",
  86. copy_visibility_to_files: true,
  87. current_user: "au courant",
  88. email_owner: true,
  89. test_mode: true,
  90. verbose: false )
  91. }
  92. 1 it "calls deactivate_embargo" do
  93. 1 expect(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  94. "from",
  95. "object class",
  96. "@email_owner=true",
  97. "@skip_file_sets=true",
  98. "@test_mode=true",
  99. ""]
  100. 1 subject.instance_variable_get(:@now) == DateTime.new(2025, 6, 1)
  101. 1 subject.instance_variable_get(:@assets) == [mock_asset_2]
  102. 1 expect(subject).not_to receive(:run_msg)
  103. 1 expect(::ActiveFedora::Base).to receive(:find).with("101").and_return "basic"
  104. 1 expect(Deepblue::ProvenanceHelper).to receive(:system_as_current_user).and_return "au courant"
  105. 1 expect(subject).to receive(:deactivate_embargo).with(curation_concern: "basic",
  106. copy_visibility_to_files: true,
  107. current_user: "au courant",
  108. email_owner: true,
  109. test_mode: true,
  110. verbose: false )
  111. 1 subject.run
  112. end
  113. end
  114. 1 context "when verbose is true and @skip_file_sets is false" do
  115. 2 subject { described_class.new( skip_file_sets: false, verbose: true) }
  116. 1 before {
  117. 1 allow(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  118. "from",
  119. ""]
  120. 1 allow(subject).to receive(:run_msg).with "The number of assets with expired embargoes is: 1"
  121. 1 allow(subject).to receive(:run_msg).with "0 - 101, FileSet, typographic, solaris April 2nd 2025, sparkling clear"
  122. 1 allow(::ActiveFedora::Base).to receive(:find).with("101").and_return "basic"
  123. 1 allow(Deepblue::ProvenanceHelper).to receive(:system_as_current_user).and_return "au courant"
  124. 1 allow(subject).to receive(:deactivate_embargo).with(curation_concern: "basic",
  125. copy_visibility_to_files: true,
  126. current_user: "au courant",
  127. email_owner: true,
  128. test_mode: true,
  129. verbose: true )
  130. }
  131. 1 it "outputs messages and calls deactivate_embargo" do
  132. 1 expect(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  133. "from",
  134. "object class",
  135. "@email_owner=true",
  136. "@skip_file_sets=false",
  137. "@test_mode=true",
  138. ""]
  139. 1 subject.instance_variable_get(:@now) == DateTime.new(2025, 6, 1)
  140. 1 subject.instance_variable_get(:@assets) == [mock_asset]
  141. 1 expect(subject).to receive(:run_msg).with "The number of assets with expired embargoes is: 1"
  142. 1 expect(subject).to receive(:run_msg).with "0 - 101, FileSet, typographic, solaris April 2nd 2025, sparkling clear"
  143. 1 expect(::ActiveFedora::Base).to receive(:find).with("101").and_return "basic"
  144. 1 expect(Deepblue::ProvenanceHelper).to receive(:system_as_current_user).and_return "au courant"
  145. 1 expect(subject).to receive(:deactivate_embargo).with(curation_concern: "basic",
  146. copy_visibility_to_files: true,
  147. current_user: "au courant",
  148. email_owner: true,
  149. test_mode: true,
  150. verbose: true )
  151. 1 subject.run
  152. end
  153. end
  154. 1 context "when verbose is false and @skip_file-sets is true" do
  155. 2 subject { described_class.new( skip_file_sets: true, verbose: false) }
  156. 1 before {
  157. 1 allow(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  158. "from",
  159. ""]
  160. }
  161. 1 it "does not output messages" do
  162. 1 expect(Deepblue::LoggingHelper).to receive(:bold_debug).with ["here",
  163. "from",
  164. "object class",
  165. "@email_owner=true",
  166. "@skip_file_sets=true",
  167. "@test_mode=true",
  168. ""]
  169. 1 expect(subject).not_to receive(:run_msg)
  170. 1 expect(subject).not_to receive(:deactivate_embargo)
  171. 1 subject.instance_variable_get(:@now) == DateTime.new(2025, 6, 1)
  172. 1 subject.instance_variable_get(:@assets) == [mock_asset]
  173. 1 subject.run
  174. end
  175. end
  176. end
  177. 1 describe "#run_msg" do
  178. 1 before {
  179. 2 allow(Deepblue::LoggingHelper).to receive(:debug).with "message"
  180. }
  181. 1 context "when @to_console is false" do
  182. 1 before {
  183. 1 subject.instance_variable_set(:@to_console, false)
  184. }
  185. 1 it "calls LoggingHelper.debug" do
  186. 1 expect(Deepblue::LoggingHelper).to receive(:debug).with "message"
  187. 1 subject.run_msg "message"
  188. end
  189. end
  190. 1 context "when @to_console is true" do
  191. 1 before {
  192. 1 subject.instance_variable_set(:@to_console, true)
  193. }
  194. 1 it "calls LoggingHelper.debug" do
  195. 1 expect(Deepblue::LoggingHelper).to receive(:debug).with "message"
  196. 1 expect(subject).to receive(:puts).with("message")
  197. 1 subject.run_msg "message"
  198. end
  199. end
  200. end
  201. end

spec/services/deepblue/doi_minting_service_spec.rb

97.78% lines covered

45 relevant lines. 44 lines covered and 1 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 require 'rails_helper'
  3. 1 describe Deepblue::DoiMintingService do
  4. 1 context "when minting a new doi" do
  5. 6 subject { described_class.new( work: work, current_user: "test_doi_minting_service@umich.edu" ) }
  6. 6 let(:work) { mock_model(GenericWork, id: '123', title: ['demotitle'],
  7. creator: ['Smith, John', 'Smith, Jane', 'O\'Rielly, Kelly'])}
  8. 6 let(:work_url) { "umrdr-testing.hydra.lib.umich.edu/concern/work/#{work.id}" }
  9. 6 let(:dummy_doi) { "doi:10.5072/FK2DEAD455BEEF" }
  10. 6 let(:identifier) { instance_double(Ezid::Identifier, id: dummy_doi) }
  11. 1 before do
  12. 5 allow(Rails).to receive_message_chain("application.routes.url_helpers.hyrax_data_set_url").and_return(work_url)
  13. 5 allow(work).to receive(:save)
  14. 5 allow(work).to receive(:reload)
  15. 5 allow(work).to receive(:doi).and_return(identifier.id)
  16. 5 allow(work).to receive(:doi=)
  17. 5 allow(work).to receive(:provenance_mint_doi)
  18. 5 allow(subject).to receive(:doi_server_reachable?).and_return(true)
  19. 5 allow(Ezid::Identifier).to receive(:mint).and_return(identifier)
  20. end
  21. 1 it "has expected metadata" do
  22. 1 expect(subject.metadata.datacite_title).to eq(work.title.first)
  23. 1 expect(subject.metadata.datacite_publisher).to eq(described_class::PUBLISHER)
  24. 1 expect(subject.metadata.datacite_publicationyear).to eq(Date.today.year.to_s)
  25. 1 expect(subject.metadata.datacite_resourcetype).to eq(described_class::RESOURCE_TYPE)
  26. 1 expect(subject.metadata.datacite_creator).to eq(work.creator.join(';'))
  27. 1 expect(subject.metadata.target).not_to be_empty
  28. end
  29. 1 it "calls out to EZID to mint a doi" do
  30. 1 expect(Ezid::Identifier).to receive(:mint)
  31. 1 subject.run
  32. end
  33. 1 it "returns the id value of the identifier" do
  34. 1 expect(subject.run).to eq(identifier.id)
  35. end
  36. 1 it "assigns the doi value and saves the work" do
  37. 1 expect(work).to receive(:doi=).with(identifier.id)
  38. 1 expect(work).to receive(:save)
  39. 1 subject.run
  40. end
  41. 1 context "EZID service is unreachable" do
  42. 1 before do
  43. 1 allow(subject).to receive(:doi_server_reachable?).and_return(false)
  44. end
  45. 1 it "does not attempt to mint a doi" do
  46. 1 expect(subject).not_to receive(:mint_doi)
  47. 1 expect(subject.run).to eq "doi:10.5072/FK2DEAD455BEEF"
  48. end
  49. end
  50. end
  51. 1 context "when actually calling out to service" do
  52. 1 let(:work) { GenericWork.new(id: '123', title: ['demotitle'],
  53. creator: ['Smith, John', 'Smith, Jane', 'O\'Rielly, Kelly'])}
  54. 1 let( :current_user ) { "test_doi_minting_service@umich.edu" }
  55. 1 it "mints a doi" do
  56. 1 skip unless ENV['INTEGRATION']
  57. expect(described_class.mint_doi_for( work: work, current_user: current_user ) ).to start_with 'doi:10.5072/FK2'
  58. end
  59. end
  60. end

spec/services/deepblue/log_exporter_spec.rb

100.0% lines covered

84 relevant lines. 84 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 class OutputMock
  3. 1 def puts (text)
  4. 1 text
  5. end
  6. end
  7. 1 RSpec.describe Deepblue::LogExporter do
  8. 10 let(:setup_output) { OutputMock.new }
  9. 10 subject { described_class.new( filter: nil, input: "input", output: setup_output) }
  10. 1 describe 'constants' do
  11. 1 it do
  12. 1 expect( Deepblue::LogExporter::DEFAULT_PP_EXPORT ).to eq false
  13. end
  14. end
  15. 1 describe "#initialize" do
  16. 1 it "calls super" do
  17. 1 skip "Add a test"
  18. end
  19. 1 context "when verbose is false" do
  20. 1 it "sets instance variables" do
  21. 1 subject.instance_variable_get(:@output) == setup_output
  22. 1 subject.instance_variable_get(:@pp_export) == false
  23. end
  24. end
  25. 1 context "when verbose is true" do
  26. 1 it "sets instance variables, calls puts method" do
  27. 1 skip "Add a test"
  28. end
  29. end
  30. end
  31. 1 describe "#export_line" do
  32. 1 context "when pp_export is equivalent to true" do
  33. 1 before {
  34. 1 allow(subject).to receive(:pp_export).and_return true
  35. }
  36. 1 it "calls pretty_print_line" do
  37. 1 expect(subject).to receive(:pretty_print_line).with "line", "timestamp", "event", "event_note", "class_name", "id", "raw"
  38. 1 subject.export_line "line", "timestamp", "event", "event_note", "class_name", "id", "raw"
  39. end
  40. end
  41. 1 context "when pp_export is equivalent to false" do
  42. 1 before {
  43. 1 allow(subject).to receive(:pp_export).and_return false
  44. }
  45. 1 it "calls @output.puts" do
  46. 1 expect(subject.export_line"line", "timestamp", "event", "event_note", "class_name", "id", "raw")
  47. .to eq "line"
  48. end
  49. end
  50. end
  51. 1 describe "#pretty_print_line" do
  52. 1 before {
  53. 1 allow(subject.output).to receive(:puts).with("timestamp event/event_note/class_name/id")
  54. 1 allow(subject.output).to receive(:puts).with("{\n \"foo\": \"bar\",\n \"ping\": \"pong\"\n}")
  55. }
  56. 1 it "calls @output.puts twice" do
  57. 1 expect(subject.output).to receive(:puts).with("timestamp event/event_note/class_name/id")
  58. 1 expect(subject.pretty_print_line "line", "timestamp", "event", "event_note", "class_name", "id", '{"foo":"bar", "ping":"pong"}')
  59. end
  60. end
  61. 1 describe "#output_mode" do
  62. 1 context "when @output_mode has no value" do
  63. 1 before {
  64. 1 allow(subject).to receive(:option).with(key: 'output_mode', default_value: 'w').and_return "output_mode=w"
  65. }
  66. 1 it "sets and returns output mode" do
  67. 1 expect(subject).to receive(:option).with(key: 'output_mode', default_value: 'w')
  68. 1 expect(subject.output_mode).to eq "output_mode=w"
  69. 1 subject.instance_variable_get(:@output_mode) == "output_mode=w"
  70. end
  71. end
  72. 1 context "when @output_mode has a value" do
  73. 1 before {
  74. 1 subject.instance_variable_set(:@output_mode, "high value")
  75. 1 allow(subject).to receive(:option).with(key: 'output_mode', default_value: 'w').and_return "output_mode=w"
  76. }
  77. 1 it "sets and returns output mode" do
  78. 1 expect(subject).not_to receive(:option).with(key: 'output_mode', default_value: 'w')
  79. 1 expect(subject.output_mode).to eq "high value"
  80. 1 subject.instance_variable_get(:@output_mode) == "high value"
  81. end
  82. end
  83. end
  84. 1 describe "#run" do
  85. 1 before {
  86. 2 allow(subject).to receive(:log_open_output)
  87. 2 allow(subject).to receive(:readlines).and_return( "line",
  88. "timestamp",
  89. "event",
  90. "event_note",
  91. "class_name",
  92. "id",
  93. "raw_key_values" )
  94. 2 allow(subject).to receive(:log_close_output)
  95. }
  96. 1 it "calls log_open_output, readlines, and log_close_output" do
  97. 1 expect(subject).to receive(:log_open_output)
  98. 1 expect(subject).to receive(:readlines)
  99. 1 expect(subject).to receive(:log_close_output)
  100. 1 subject.run
  101. 1 subject.instance_variable_get(:@lines_exported) == 1
  102. end
  103. 1 it "calls export_line" do
  104. 1 skip "Add a test"
  105. end
  106. end
  107. 1 describe "#quick_report" do
  108. 1 before {
  109. # stubbing for super
  110. 1 subject.instance_variable_set(:@input_pathname, "strawberries")
  111. 1 subject.instance_variable_set(:@lines_read, "watermelon")
  112. 1 subject.instance_variable_set(:@lines_parsed, "yuzu")
  113. 1 subject.instance_variable_set(:@output_pathname, "bananas")
  114. 1 subject.instance_variable_set(:@lines_exported, "oranges")
  115. }
  116. 1 it "calls super, outputs text" do
  117. # super expectations
  118. 1 expect(subject).to receive(:puts).with no_args
  119. 1 expect(subject).to receive(:puts).with "Quick report"
  120. 1 expect(subject).to receive(:puts).with "input_pathname: strawberries"
  121. 1 expect(subject).to receive(:puts).with "lines_read: watermelon"
  122. 1 expect(subject).to receive(:puts).with "lines_parsed: yuzu"
  123. 1 expect(subject).to receive(:puts).with "output_pathname: bananas"
  124. 1 expect(subject).to receive(:puts).with "lines_exported: oranges"
  125. 1 subject.quick_report
  126. end
  127. end
  128. end

spec/services/deepblue/log_reader_spec.rb

100.0% lines covered

174 relevant lines. 174 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 class MockLogFilter
  3. 1 def initialize ( all_log_filter = false )
  4. 29 @all_log_filter = all_log_filter
  5. end
  6. 1 def all_log_filter?
  7. 6 @all_log_filter
  8. end
  9. 1 def and ( new_filters: )
  10. 1 "bran flakes"
  11. end
  12. 1 def to_ary
  13. 4 [self]
  14. end
  15. 1 def or (new_filters: )
  16. 1 "corn flakes"
  17. end
  18. end
  19. 1 RSpec.describe Deepblue::LogReader do
  20. 20 let( :initial_filter ) { MockLogFilter.new all_log_filter: true}
  21. 20 subject { described_class.new(filter: initial_filter, input: "input", options: {"red" => "green"} ) }
  22. 1 describe 'constants' do
  23. 1 it do
  24. 1 expect( Deepblue::LogReader::DEFAULT_BEGIN_TIMESTAMP ).to be_blank
  25. 1 expect( Deepblue::LogReader::DEFAULT_END_TIMESTAMP ).to be_blank
  26. 1 expect( Deepblue::LogReader::DEFAULT_TIMESTAMP_FORMAT ).to be_blank
  27. 1 expect( Deepblue::LogReader::DEFAULT_VERBOSE ).to eq false
  28. 1 expect( Deepblue::LogReader::DEFAULT_VERBOSE_FILTER ).to eq false
  29. end
  30. end
  31. 1 describe "#initialize" do
  32. 1 it "sets instance variables" do
  33. 1 subject.instance_variable_get(:@filter) == initial_filter
  34. 1 subject.instance_variable_get(:@input) == "input"
  35. 1 subject.instance_variable_get(:@options) == {"red" => "green"}
  36. 1 subject.instance_variable_get(:@verbose) == false
  37. 1 subject.instance_variable_get(:@verbose_filter) == false
  38. end
  39. 1 it "calls add_date_range_filter" do
  40. 1 skip "Add a test"
  41. end
  42. end
  43. 1 describe "#initialize_filter" do
  44. 1 context "when filter is blank" do
  45. 1 before {
  46. 1 allow(Deepblue::AllLogFilter).to receive(:new)
  47. }
  48. 1 it "calls AllLogFilter.new" do
  49. 1 expect(Deepblue::AllLogFilter).to receive(:new)
  50. 1 expect(subject.initialize_filter nil).to be_blank
  51. end
  52. end
  53. 1 context "when filter is an array" do
  54. 1 before {
  55. 1 allow(Deepblue::AndLogFilter).to receive(:new).with( filters: ["filtration", "salination"], options: {}).and_return "particulate matter"
  56. }
  57. 1 it "calls AndLogFilter.new" do
  58. 1 allow(Deepblue::AndLogFilter).to receive(:initialize).with( filters: ["filtration", "salination"], options: {})
  59. 1 expect(subject.initialize_filter ["filtration", "salination"]).to eq "particulate matter"
  60. end
  61. end
  62. 1 context "when filter is not an array and not blank" do
  63. 1 it "returns filter" do
  64. 1 expect(subject.initialize_filter "condensation").to eq "condensation"
  65. end
  66. end
  67. end
  68. 1 describe "#add_date_range_filter" do
  69. 1 context "when option function returns blank every time" do
  70. 1 before {
  71. 1 allow(subject).to receive("option").with(key: 'begin')
  72. 1 allow(subject).to receive("option").with(key: 'begin_timestamp', default_value: '')
  73. 1 allow(subject).to receive("option").with(key: 'end')
  74. 1 allow(subject).to receive("option").with(key: 'end_timestamp', default_value: '')
  75. 1 allow(subject).to receive("option").with(key: 'format')
  76. 1 allow(subject).to receive("option").with(key: 'timestamp_format', default_value: '')
  77. 1 allow(subject).to receive("verbose_filter").and_return(false)
  78. }
  79. 1 it "returns nil" do
  80. 1 expect(subject).to receive("option").with(key: 'begin')
  81. 1 expect(subject).to receive("option").with(key: 'begin_timestamp', default_value: '')
  82. 1 expect(subject).to receive("option").with(key: 'end')
  83. 1 expect(subject).to receive("option").with(key: 'end_timestamp', default_value: '')
  84. 1 expect(subject).to receive("option").with(key: 'format')
  85. 1 expect(subject).to receive("option").with(key: 'timestamp_format', default_value: '')
  86. 1 expect(subject.add_date_range_filter).to be_blank
  87. end
  88. end
  89. 1 context "when begin_timestamp and end_timestamp not blank and verbose_filter" do
  90. 1 before {
  91. 1 allow(subject).to receive("option").with(key: 'begin').and_return( "good times" )
  92. 1 allow(subject).to receive("option").with(key: 'end').and_return( "best times" )
  93. 1 allow(subject).to receive("option").with(key: 'format').and_return( "worst times" )
  94. 1 allow(subject).to receive("verbose_filter").and_return( true )
  95. 1 allow(Deepblue::DateLogFilter).to receive("new").with( begin_timestamp: "good times" ,
  96. end_timestamp: "best times" ,
  97. timestamp_format: "worst times",
  98. options: Hash.new(["wherefore" => "whyfor"]) )
  99. .and_return( "home on the range" )
  100. 1 allow(subject).to receive("filter_and").with( new_filters: "home on the range" )
  101. }
  102. 1 it "calls DateLogFilter.new and filter_and" do
  103. 1 expect(subject).to receive("option").with(key: 'begin')
  104. 1 expect(subject).to receive("option").with(key: 'end')
  105. 1 expect(subject).to receive("option").with(key: 'format')
  106. 1 expect(subject).to receive("puts").with "add_date_range_filter begin_timestamp=good times end_timestamp=best times"
  107. 1 expect(Deepblue::DateLogFilter).to receive("new").with( begin_timestamp: "good times" ,
  108. end_timestamp: "best times" ,
  109. timestamp_format: "worst times",
  110. options: Hash.new(["wherefore" => "whyfor"]) )
  111. 1 expect(subject).to receive("filter_and").with( new_filters: "home on the range" )
  112. 1 expect(subject.add_date_range_filter options: Hash.new(["wherefore" => "whyfor"])).to be_blank
  113. end
  114. end
  115. end
  116. 1 describe "#filter_and" do
  117. 1 context "when new_filters is blank" do
  118. 1 it "returns blank" do
  119. 1 expect(subject.filter_and new_filters: nil).to be_blank
  120. end
  121. end
  122. 1 context "when verbose" do
  123. 1 before {
  124. 1 allow(subject).to receive(:verbose).and_return(true)
  125. 1 allow(subject).to receive(:filter_refresh).with( current_filter: initial_filter, new_filters: "consonant", append: true, options: {} )
  126. .and_return "globalization"
  127. 1 allow(subject).to receive(:puts).with( "filter_and @filter=globalization" )
  128. }
  129. 1 it "outputs string" do
  130. 1 expect(subject).to receive(:filter_refresh).with( current_filter: initial_filter, new_filters: "consonant", append: true, options: {} )
  131. 1 expect(subject).to receive(:puts).with("filter_and @filter=globalization" )
  132. 1 subject.filter_and new_filters: "consonant"
  133. end
  134. end
  135. end
  136. 1 describe "#filter_refresh" do
  137. 1 context "when current_filter.all_log_filter is true and new_filters is an array" do
  138. 1 before {
  139. 1 allow(Deepblue::AndLogFilter).to receive(:new).with( filters: ["pop", "corn"], options: {} ).and_return "cornflakes"
  140. }
  141. 1 it "return new_filters" do
  142. 1 expect(subject.filter_refresh current_filter: MockLogFilter.new( all_log_filter = true ), new_filters: ["pop", "corn"]).to eq "cornflakes"
  143. end
  144. end
  145. 1 context "when current_filter.all_log_filter is true and new_filters is not an array" do
  146. 1 it "return new_filters" do
  147. 1 expect(subject.filter_refresh current_filter: MockLogFilter.new( all_log_filter = true ), new_filters: "brand new").to eq "brand new"
  148. end
  149. end
  150. 1 context "when current_filter.all_log_filter is false and append is true" do
  151. 1 it "return new_filters" do
  152. 1 expect(subject.filter_refresh current_filter: MockLogFilter.new, new_filters: "brand new", append: true).to eq "bran flakes"
  153. end
  154. end
  155. 1 context "when current_filter.all_log_filter is false and append is false" do
  156. 1 it "return new_filters" do
  157. 1 currentFilter = MockLogFilter.new
  158. 1 newFilter = MockLogFilter.new
  159. 1 expect(Deepblue::AndLogFilter).to receive(:new).with(filters: [newFilter, currentFilter], options: {1 => "Alpha"})
  160. 1 expect(subject.filter_refresh current_filter: currentFilter, new_filters: newFilter, append: false, options: {1 => "Alpha"})
  161. end
  162. end
  163. end
  164. 1 describe "#filter_or" do
  165. 1 context "when new_filters is blank" do
  166. 1 it "returns blank" do
  167. 1 expect(subject.filter_or new_filters: []).to be_blank
  168. end
  169. end
  170. 1 context "when new_filters is not blank and LogReader initialized with filter that has all_log_filter true" do
  171. 1 it "when current_filter all_log_filter is true" do
  172. 1 expect(subject.filter_or new_filters: MockLogFilter.new, append: true).to eq initial_filter
  173. end
  174. end
  175. 1 context "when new_filters is not blank and LogReader initialized with filter that has all_log_filter false" do
  176. 2 subject { described_class.new(filter: MockLogFilter.new, input: "input" ) }
  177. 1 it "returns current_filter or new_filters when append is true" do
  178. 1 expect(subject.filter_or new_filters: MockLogFilter.new, append: true).to eq "corn flakes"
  179. end
  180. end
  181. 1 context "when new_filters is not blank and LogReader initialized with filter that has all_log_filter false and append false" do
  182. 1 firstFilter = MockLogFilter.new
  183. 1 secondFilter = MockLogFilter.new
  184. 2 subject { described_class.new(filter: firstFilter, input: "input" ) }
  185. 1 it "returns " do
  186. 1 expect(Deepblue::OrLogFilter).to receive(:new).with(filters: [secondFilter, firstFilter], options: {10 => "Omega"})
  187. 1 subject.filter_or new_filters: secondFilter, append: false, options: {10 => "Omega"}
  188. end
  189. end
  190. end
  191. 1 describe "#input_mode" do
  192. 1 before {
  193. 1 allow(subject).to receive(:option).with(key: 'input_mode', default_value: 'r').and_return ("trail mix")
  194. }
  195. 1 it "calls option function" do
  196. 1 expect(subject).to receive(:option).with(key: 'input_mode', default_value: 'r')
  197. 1 expect(subject.input_mode).to eq "trail mix"
  198. end
  199. end
  200. 1 describe "#parse_line" do
  201. 1 context "when @current_line is blank" do
  202. 1 before {
  203. 1 subject.instance_variable_set(:@current_line, " ")
  204. }
  205. 1 it "returns" do
  206. 1 expect(Deepblue::ProvenanceHelper).not_to receive(:parse_log_line).with any_args
  207. 1 subject.parse_line
  208. end
  209. end
  210. 1 context "when LogParseError is raised" do
  211. 1 before {
  212. 1 subject.instance_variable_set(:@current_line, "linear")
  213. 1 subject.instance_variable_set(:@lines_read, 22)
  214. 1 allow(Deepblue::ProvenanceHelper).to receive(:parse_log_line).and_raise(Deepblue::LogParseError, "log parse error")
  215. }
  216. 1 it "puts LogParseError message" do
  217. 1 expect(subject).to receive(:puts).with("log parse error")
  218. 1 subject.parse_line
  219. end
  220. end
  221. 1 context "when @current_line is not blank" do
  222. 1 before {
  223. 1 subject.instance_variable_set(:@current_line, "linear")
  224. 1 subject.instance_variable_set(:@lines_read, 22)
  225. 1 subject.instance_variable_set(:@lines_parsed, 0)
  226. }
  227. 1 it "calls ProvenanceHelper" do
  228. 1 expect(Deepblue::ProvenanceHelper).to receive(:parse_log_line).with("linear", line_number: 22, raw_key_values: true)
  229. 1 subject.parse_line
  230. 1 subject.instance_variable_get(:@lines_parsed) == 1
  231. 1 subject.instance_variable_get(:@parsed) == true
  232. end
  233. end
  234. end
  235. 1 describe "#quick_report" do
  236. 1 before {
  237. 1 subject.instance_variable_set(:@input_pathname, "strawberries")
  238. 1 subject.instance_variable_set(:@lines_read, "watermelon")
  239. 1 subject.instance_variable_set(:@lines_parsed, "yuzu")
  240. }
  241. 1 it "outputs text" do
  242. 1 expect(subject).to receive(:puts).with no_args
  243. 1 expect(subject).to receive(:puts).with "Quick report"
  244. 1 expect(subject).to receive(:puts).with "input_pathname: strawberries"
  245. 1 expect(subject).to receive(:puts).with "lines_read: watermelon"
  246. 1 expect(subject).to receive(:puts).with "lines_parsed: yuzu"
  247. 1 subject.quick_report
  248. end
  249. end
  250. 1 pending "#readlines"
  251. end

spec/services/deepblue/log_reporter_spec.rb

100.0% lines covered

43 relevant lines. 43 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 RSpec.describe Deepblue::LogReporter do
  3. 5 subject { described_class.new(filter: "filter", input: "input", options: {"blue" => "gold"} ) }
  4. 1 describe "#initialize" do
  5. 1 it "initializes instance variables" do
  6. # called by initialize in parent class
  7. 1 subject.instance_variable_get(:@filter) == "filter"
  8. 1 subject.instance_variable_get(:@input) == "input"
  9. 1 subject.instance_variable_get(:@options) == {"blue" => "gold"}
  10. 1 subject.instance_variable_get(:@verbose) == false
  11. 1 subject.instance_variable_get(:@verbose_filter) == false
  12. 1 subject.instance_variable_get(:@output_close) == false
  13. 1 subject.instance_variable_get(:@output_mode) == 'w'
  14. 1 subject.instance_variable_get(:@output_pathname).nil? == true
  15. end
  16. 1 it "super calls add_date_range_filter" do
  17. 1 allow(Deepblue::LogReader).to receive(:new)
  18. 1 Deepblue::LogReporter.new(filter: nil, input:"input", options: {})
  19. 1 expect(Deepblue::LogReader).to have_received(:new)
  20. end
  21. end
  22. 1 describe "#report" do
  23. 1 before {
  24. 1 allow(subject).to receive(:run)
  25. 1 subject.instance_variable_set(:@timestamp_first, "first!")
  26. 1 subject.instance_variable_set(:@timestamp_last, "last...")
  27. 1 allow(subject).to receive(:ids).and_return "1,2,3"
  28. 1 allow(subject).to receive(:events).and_return "eventually"
  29. 1 allow(subject).to receive(:class_events).and_return "classified"
  30. }
  31. 1 it "puts messages" do
  32. 1 expect(subject).to receive(:puts).with "timestamp_first = first!"
  33. 1 expect(subject).to receive(:puts).with "timestamp_last = last..."
  34. 1 expect(subject).to receive(:puts).with "ids = 1,2,3"
  35. 1 expect(subject).to receive(:puts).with "events = eventually"
  36. 1 expect(subject).to receive(:puts).with "class_events = classified"
  37. 1 expect(subject).to receive(:run)
  38. 1 subject.report
  39. end
  40. end
  41. 1 describe "#run" do
  42. 1 before {
  43. 2 allow(subject).to receive(:initialize_report_values)
  44. 2 allow(subject).to receive(:readlines).and_return( ["line", "timestamp", "event", "event_note", "class_name", "id", "raw_key_values"] )
  45. }
  46. 1 it "calls functions" do
  47. 1 expect(subject).to receive(:initialize_report_values)
  48. 1 expect(subject).to receive(:readlines).and_return( ["line", "timestamp", "event", "event_note", "class_name", "id", "raw_key_values"] )
  49. 1 subject.run
  50. end
  51. 1 it "calls line_read" do
  52. 1 skip "Add a test"
  53. end
  54. end
  55. end

spec/services/deepblue/logging_callback_spec.rb

100.0% lines covered

49 relevant lines. 49 lines covered and 0 lines missed.
    
  1. # frozen_string_literal: true
  2. 1 RSpec.describe Deepblue::LoggingCallback do
  3. 6 let( :event_name ) { 'the_event_name' }
  4. 6 let( :event_line ) { ">>>>> #{event_name} >>>>>" }
  5. 3 let( :msg ) { 'The message.' }
  6. 5 let( :user ) { 'user@umich.edu' }
  7. 1 describe '.process_event' do
  8. # subject { lambda { |event_name, msg| Deepblue::LoggingCallback.process_event( event_name: event_name, msg: msg ) } }
  9. 1 before do
  10. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  11. end
  12. 1 it do
  13. 1 described_class.process_event( event_name: event_name, msg: msg )
  14. 1 expect( Rails.logger ).to have_received( :debug ).with( event_line ).exactly( 4 ).times
  15. 1 expect( Rails.logger ).to have_received( :debug ).with( "#{event_name} >>>>> #{msg}" )
  16. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 5 ).times
  17. end
  18. end
  19. 1 describe '.process_event_curation_concern' do
  20. 2 let( :curation_concern ) { 'DataSet XYZ' }
  21. 1 before do
  22. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  23. end
  24. 1 it do
  25. 1 described_class.process_event_curation_concern( event_name: event_name, curation_concern: curation_concern, user: user )
  26. 1 expect( Rails.logger ).to have_received( :debug ).with( event_line ).exactly( 4 ).times
  27. 1 expect( Rails.logger ).to have_received( :debug ).with( "#{event_name} >>>>> #{user} >>>>> #{curation_concern}" )
  28. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 5 ).times
  29. end
  30. end
  31. 1 describe '.process_event_file_set' do
  32. 2 let( :file_set ) { 'FileSet XYZ' }
  33. 1 before do
  34. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  35. end
  36. 1 it do
  37. 1 described_class.process_event_file_set( event_name: event_name, file_set: file_set, user: user )
  38. 1 expect( Rails.logger ).to have_received( :debug ).with( event_line ).exactly( 4 ).times
  39. 1 expect( Rails.logger ).to have_received( :debug ).with( "#{event_name} >>>>> #{user} >>>>> #{file_set}" )
  40. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 5 ).times
  41. end
  42. end
  43. 1 describe '.process_event_user' do
  44. 1 context 'with msg' do
  45. 1 before do
  46. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  47. end
  48. 1 it do
  49. 1 described_class.process_event_user( event_name: event_name, user: user, msg: msg )
  50. 1 expect( Rails.logger ).to have_received( :debug ).with( event_line ).exactly( 4 ).times
  51. 1 expect( Rails.logger ).to have_received( :debug ).with( "#{event_name} >>>>> #{user} >>>>> #{msg}" )
  52. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 5 ).times
  53. end
  54. end
  55. 1 context 'without msg' do
  56. 1 before do
  57. 1 allow( Rails.logger ).to receive( :debug ).with( any_args )
  58. end
  59. 1 it do
  60. 1 described_class.process_event_user( event_name: event_name, user: user, msg: '' )
  61. 1 described_class.process_event_user( event_name: event_name, user: user, msg: nil )
  62. 1 expect( Rails.logger ).to have_received( :debug ).with( event_line ).exactly( 8 ).times
  63. 1 expect( Rails.logger ).to have_received( :debug ).with( "#{event_name} >>>>> #{user}" ).twice
  64. 1 expect( Rails.logger ).to have_received( :debug ).exactly( 10 ).times
  65. end
  66. end
  67. end
  68. end

spec/services/deepblue/virus_scan_service_spec.rb

100.0% lines covered

39 relevant lines. 39 lines covered and 0 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 class VirusScanServiceMock
  3. 1 include ::Deepblue::VirusScanService
  4. end
  5. 1 RSpec.describe Deepblue::VirusScanService do
  6. 8 subject { VirusScanServiceMock.new }
  7. 1 describe 'constants' do
  8. 1 it do
  9. 1 expect( Deepblue::VirusScanService::VIRUS_SCAN_ERROR ).to eq 'scan error'
  10. 1 expect( Deepblue::VirusScanService::VIRUS_SCAN_NOT_VIRUS ).to eq 'not virus'
  11. 1 expect( Deepblue::VirusScanService::VIRUS_SCAN_SKIPPED ).to eq 'scan skipped'
  12. 1 expect( Deepblue::VirusScanService::VIRUS_SCAN_SKIPPED_SERVICE_UNAVAILABLE ).to eq 'scan skipped service unavailable'
  13. 1 expect( Deepblue::VirusScanService::VIRUS_SCAN_SKIPPED_TOO_BIG ).to eq 'scan skipped too big'
  14. 1 expect( Deepblue::VirusScanService::VIRUS_SCAN_UNKNOWN ).to eq 'scan unknown'
  15. 1 expect( Deepblue::VirusScanService::VIRUS_SCAN_VIRUS ).to eq 'virus'
  16. end
  17. end
  18. 1 describe "#virus_scan_detected_virus?" do
  19. 1 context "when argument equals VIRUS_SCAN_VIRUS constant" do
  20. 1 it "returns true" do
  21. 1 expect(subject.virus_scan_detected_virus? scan_result: "virus").to eq true
  22. end
  23. end
  24. 1 context "when argument does not equal VIRUS_SCAN_VIRUS constant" do
  25. 1 it "returns false" do
  26. 1 expect(subject.virus_scan_detected_virus? scan_result: "scanned virus").to eq false
  27. end
  28. end
  29. end
  30. 1 describe "#virus_scan_service_name" do
  31. 1 it do
  32. 1 expect(subject.virus_scan_service_name).to eq Hydra::Works.default_system_virus_scanner.name
  33. end
  34. end
  35. 1 describe "#virus_scan_skipped?" do
  36. 1 context "if scan_result blank" do
  37. 1 it "returns false" do
  38. 1 expect(subject.virus_scan_skipped? scan_result: "").to eq false
  39. end
  40. end
  41. 1 context "if scan_result does not start with 'scan skipped'" do
  42. 1 it "returns false" do
  43. 1 expect(subject.virus_scan_skipped? scan_result: "scanning the surrounding parsecs").to eq false
  44. end
  45. end
  46. 1 context "if scan_result does start with 'scan skipped'" do
  47. 1 it "returns true" do
  48. 1 expect(subject.virus_scan_skipped? scan_result: "scan skipped, yippee ki yi yay").to eq true
  49. end
  50. end
  51. end
  52. 1 describe "#virus_scan_timestamp_now" do
  53. 1 before {
  54. 1 allow(Time).to receive(:now).and_return(DateTime.new(2025, 2, 3, 4, 5, 6))
  55. }
  56. 1 it do
  57. 1 expect(subject.virus_scan_timestamp_now).to eq "2025-02-03 04:05:06"
  58. end
  59. end
  60. end

spec/services/deepblue/yaml_populate_service_spec.rb

99.67% lines covered

614 relevant lines. 612 lines covered and 2 lines missed.
    
  1. 1 require 'rails_helper'
  2. 1 class MockOutput
  3. 1 def puts text
  4. text
  5. end
  6. end
  7. 1 class MockFileSet
  8. 1 def original_name
  9. 1 "original name"
  10. end
  11. 1 def to_s
  12. "file name"
  13. end
  14. end
  15. 1 RSpec.describe Deepblue::YamlPopulateService do
  16. 68 subject { described_class.new }
  17. 1 def expected_attribute_names_ignore
  18. 3 %w[ access_control_id
  19. collection_type_gid
  20. file_size
  21. head
  22. part_of tail
  23. thumbnail_id ]
  24. end
  25. 1 def expected_attribute_names_user_ignore
  26. 1 %w[ current_sign_in_at
  27. current_sign_in_ip
  28. reset_password_token
  29. reset_password_sent_at ]
  30. end
  31. 1 describe 'constants' do
  32. 1 it do
  33. 1 expect( Deepblue::YamlPopulateService::DEFAULT_CREATE_ZERO_LENGTH_FILES ).to eq true
  34. 1 expect( Deepblue::YamlPopulateService::DEFAULT_OVERWRITE_EXPORT_FILES ).to eq true
  35. end
  36. end
  37. 1 describe "#initialize" do
  38. 1 it "sets instance variables" do
  39. 1 instance_variable_get(:@create_zero_length_files) == true
  40. 1 instance_variable_get(:@mode) == 'build'
  41. 1 instance_variable_get(:@overwrite_export_files) == true
  42. 1 instance_variable_get(:@source) == 'DBDv2'
  43. 1 instance_variable_get(:@total_collections_exported) == 0
  44. 1 instance_variable_get(:@total_file_sets_exported) == 0
  45. 1 instance_variable_get(:@total_file_sets_size_exported) == 0
  46. 1 instance_variable_get(:@total_works_exported) == 0
  47. 1 instance_variable_get(:@total_users_exported) == 0
  48. end
  49. end
  50. 1 describe "#yaml_body_collections" do
  51. 1 context do
  52. 1 concern = OpenStruct.new(id: "XYZ-1000", edit_users: "editors", collection_type: OpenStruct.new(machine_id: "HAL"),
  53. work_ids: [101,202,303,404], total_file_size: 203, visibility: "public")
  54. 1 before {
  55. 1 allow(subject).to receive(:yaml_item).with "out", "concave", ":id:", "XYZ-1000"
  56. 1 allow(subject).to receive(:source).and_return 'DBDv2'
  57. 1 allow(subject).to receive(:yaml_item).with "out", "concave", ":collection_type:", "HAL", escape: true
  58. 1 allow(subject).to receive(:yaml_item).with "out", "concave", ":edit_users:", "editors", escape: true
  59. 1 allow(subject).to receive(:yaml_item_prior_identifier).with "out", "concave", curation_concern: concern
  60. 1 allow(subject).to receive(:yaml_item_subject).with "out", "concave", curation_concern: concern
  61. 1 allow(subject).to receive(:yaml_item).with "out", "concave", ":total_work_count:", 4
  62. 1 allow(subject).to receive(:yaml_item).with "out", "concave", ":total_file_size:", 203
  63. 1 allow(subject).to receive(:human_readable_size).with( 203 ).and_return "203 MB"
  64. 1 allow(subject).to receive(:yaml_item).with "out", "concave", ":total_file_size_human_readable:", "203 MB", escape: true
  65. 1 allow(subject).to receive(:yaml_item).with "out", "concave", ":visibility:", "public"
  66. 1 allow(subject).to receive(:attribute_names_collection).and_return %w[ prior_identifier rights rights_license
  67. subject subject_discipline total_file_size visionary ]
  68. 1 allow(subject).to receive(:yaml_item_collection).with "out", "concave", concern, name: "visionary"
  69. }
  70. 1 it "calls functions with curation_concern values" do
  71. 1 instance_variable_get(:@total_collections_exported) == 0
  72. 1 expect(subject).to receive(:yaml_item).with "out", "concave", ":id:", "XYZ-1000"
  73. 1 expect(subject).to receive(:yaml_item).with "out", "concave", ":collection_type:", "HAL", escape: true
  74. 1 expect(subject).to receive(:yaml_item).with "out", "concave", ":edit_users:", "editors", escape: true
  75. 1 expect(subject).to receive(:yaml_item_prior_identifier).with "out", "concave", curation_concern: concern
  76. 1 expect(subject).to receive(:yaml_item_subject).with "out", "concave", curation_concern: concern
  77. 1 expect(subject).to receive(:yaml_item).with "out", "concave", ":total_work_count:", 4
  78. 1 expect(subject).to receive(:yaml_item).with "out", "concave", ":total_file_size:", 203
  79. 1 expect(subject).to receive(:yaml_item).with "out", "concave", ":total_file_size_human_readable:", "203 MB", escape: true
  80. 1 expect(subject).to receive(:yaml_item).with "out", "concave", ":visibility:", "public"
  81. 1 expect(subject).to receive(:yaml_item_collection).with "out", "concave", concern, name: "visionary"
  82. 1 subject.yaml_body_collections "out", indent: "concave", curation_concern: concern
  83. end
  84. end
  85. end
  86. 1 describe "#yaml_file_size" do
  87. 1 context "when file_set.file_size is blank and file_set.original_file is nil" do
  88. 1 it "returns 0" do
  89. 1 fileset = OpenStruct.new(file_size: "", original_file: nil)
  90. 1 expect(subject.yaml_file_size fileset).to eq 0
  91. end
  92. end
  93. 1 context "when file_set.file_size is blank and file_set.original_file is not nil" do
  94. 1 it "returns file_set.original_file.size" do
  95. 1 fileset = OpenStruct.new(file_size: "", original_file: OpenStruct.new(size: 80))
  96. 1 expect(subject.yaml_file_size fileset).to eq 80
  97. end
  98. end
  99. 1 context "when file_set.file_size is not blank" do
  100. 1 it "returns file_set.file_size[0]" do
  101. 1 fileset = OpenStruct.new(file_size: [9], original_file: OpenStruct.new(size: 80))
  102. 1 expect(subject.yaml_file_size fileset).to eq 9
  103. end
  104. end
  105. end
  106. 1 describe "#yaml_body_files" do
  107. 1 before {
  108. 2 allow(subject).to receive(:yaml_line).with("out", "indent", ":file_set_ids:")
  109. }
  110. 1 context "curation_concern.file_sets.count is not positive" do
  111. 1 it "calls yaml_line once" do
  112. 1 expect(subject).to receive(:yaml_line).with("out", "indent", ":file_set_ids:")
  113. 1 concern = OpenStruct.new(file_sets: [])
  114. 1 subject.yaml_body_files "out", indent_base: "base ", indent: "indent", curation_concern: concern, target_dirname: "target"
  115. end
  116. end
  117. 1 context "curation_concern.file_sets.count is positive" do
  118. 1 fileset1 = OpenStruct.new(id: 1, title: ["Why we are No. 1"], edit_users: "admin users", mime_type: "text/plain", original_checksum: ["beauty","beast"],
  119. original_file: OpenStruct.new(original_name: "When we were No. 2"), visibility: "public")
  120. 1 concern = OpenStruct.new(file_sets: [fileset1])
  121. # TODO: put YamlPopulateService.rb edits in earlier commit
  122. #
  123. 1 before {
  124. 1 allow(subject).to receive(:yaml_item).with("out", "baseindent-", "", 1, escape: true)
  125. 1 allow(subject).to receive(:mode).and_return "migrate"
  126. 1 allow(subject).to receive(:log_provenance_migrate).with( curation_concern: fileset1, parent: concern )
  127. 1 allow(subject).to receive(:yaml_file_set_id).with(fileset1).and_return "file id 1"
  128. 1 allow(subject).to receive(:yaml_line).with("out", "indent", ":file id 1:")
  129. 1 allow(subject).to receive(:yaml_item).with("out", "baseindent", ":id:", 1, escape: true)
  130. 1 allow(subject).to receive(:yaml_item).with("out", "baseindent", ':title:', ["Why we are No. 1"], escape: true, single_value: true )
  131. 1 allow(subject).to receive(:yaml_item_prior_identifier).with("out", "baseindent", curation_concern: fileset1 )
  132. 1 allow(subject).to receive(:yaml_export_file_path).with(target_dirname: "target", file_set: fileset1 ).and_return "filepath"
  133. 1 allow(subject).to receive(:yaml_item).with( "out", "baseindent", ':file_path:', "filepath", escape: true )
  134. 1 allow(subject).to receive(:yaml_file_set_checksum).with( file_set: fileset1 ).and_return OpenStruct.new(algorithm: "11", value: "111*")
  135. 1 allow(subject).to receive(:yaml_item).with( "out", "baseindent", ":checksum_algorithm:", "11", escape: true )
  136. 1 allow(subject).to receive(:yaml_item).with( "out", "baseindent", ":checksum_value:", "111*", escape: true )
  137. 1 allow(subject).to receive(:yaml_item).with( "out", "baseindent", ":edit_users:", "admin users", escape: true )
  138. 1 allow(subject).to receive(:yaml_file_size).with( fileset1 ).and_return "76"
  139. 1 allow(subject).to receive(:yaml_item).with( "out", "baseindent", ":file_size:", "76" )
  140. 1 allow(subject).to receive(:human_readable_size).with( "76" ).and_return "76 kb"
  141. 1 allow(subject).to receive(:yaml_item).with( "out", "baseindent", ":file_size_human_readable:", "76 kb", escape: true )
  142. 1 allow(subject).to receive(:yaml_item).with( "out", "baseindent", ":mime_type:", "text/plain", escape: true )
  143. 1 allow(subject).to receive(:yaml_item).with( "out", "baseindent", ":original_checksum:", "beauty" )
  144. 1 allow(subject).to receive(:yaml_item).with( "out", "baseindent", ":original_name:", "When we were No. 2", escape: true )
  145. 1 allow(subject).to receive(:yaml_item).with( "out", "baseindent", ":visibility:", "public" )
  146. 1 allow(subject).to receive(:attribute_names_file_set).and_return %w[ title file_size irascible ]
  147. 1 allow(subject).to receive(:yaml_item_file_set).with( "out", "baseindent", fileset1, name: "irascible" )
  148. }
  149. 1 it "calls yaml_item for each file set in curation_concern" do
  150. 1 expect(subject).to receive(:yaml_line).with("out", "indent", ":file_set_ids:")
  151. 1 expect(subject).to receive(:yaml_item).with("out", "baseindent-", "", 1, escape: true)
  152. 1 expect(subject).to receive(:log_provenance_migrate).with( curation_concern: fileset1, parent: concern )
  153. 1 expect(subject).to receive(:yaml_line).with("out", "indent", ":file id 1:")
  154. 1 expect(subject).to receive(:yaml_item).with("out", "baseindent", ":id:", 1, escape: true)
  155. 1 expect(subject).to receive(:yaml_item).with("out", "baseindent", ':title:', ["Why we are No. 1"], escape: true, single_value: true )
  156. 1 expect(subject).to receive(:yaml_item_prior_identifier).with("out", "baseindent", curation_concern: fileset1 )
  157. 1 expect(subject).to receive(:yaml_export_file_path).with(target_dirname: "target", file_set: fileset1 )
  158. 1 expect(subject).to receive(:yaml_item).with( "out", "baseindent", ':file_path:', "filepath", escape: true )
  159. 1 expect(subject).to receive(:yaml_file_set_checksum).with( file_set: fileset1 )
  160. 1 expect(subject).to receive(:yaml_item).with( "out", "baseindent", ":checksum_algorithm:", "11", escape: true )
  161. 1 expect(subject).to receive(:yaml_item).with( "out", "baseindent", ":checksum_value:", "111*", escape: true )
  162. 1 expect(subject).to receive(:yaml_item).with( "out", "baseindent", ":edit_users:", "admin users", escape: true )
  163. 1 expect(subject).to receive(:yaml_item).with( "out", "baseindent", ":file_size:", "76" )
  164. 1 expect(subject).to receive(:yaml_item).with( "out", "baseindent", ":file_size_human_readable:", "76 kb", escape: true )
  165. 1 expect(subject).to receive(:yaml_item).with( "out", "baseindent", ":mime_type:", "text/plain", escape: true )
  166. 1 expect(subject).to receive(:yaml_item).with( "out", "baseindent", ":original_checksum:", "beauty" )
  167. 1 expect(subject).to receive(:yaml_item).with( "out", "baseindent", ":original_name:", "When we were No. 2", escape: true )
  168. 1 expect(subject).to receive(:yaml_item).with( "out", "baseindent", ":visibility:", "public" )
  169. 1 expect(subject).to receive(:yaml_item_file_set).with( "out", "baseindent", fileset1, name: "irascible" )
  170. 1 subject.yaml_body_files "out", indent_base: "base", indent: "indent", curation_concern: concern, target_dirname: "target"
  171. 1 subject.instance_variable_get(:@total_file_sets_exported) == 1
  172. 1 subject.instance_variable_get(:@total_file_sets_size_exported) == 76
  173. end
  174. end
  175. end
  176. 1 describe "#yaml_body_user_body" do
  177. 1 user = OpenStruct.new(email: 'email z')
  178. 1 before {
  179. 1 allow(subject).to receive(:yaml_user_email).with(user).and_return "user_email_z"
  180. 1 allow(subject).to receive(:yaml_line).with( "out", "indent", ":user_email_z:")
  181. 1 allow(subject).to receive(:yaml_item).with( "out", "base indent", ":email:", "email z", escape: true)
  182. 1 allow(subject).to receive(:attribute_names_user).and_return ["snail mail", "email"]
  183. 1 allow(subject).to receive(:yaml_item_user).with("out", "base indent", user, name: "snail mail")
  184. }
  185. 1 it "calls various functions" do
  186. 1 expect(subject).to receive(:yaml_user_email).with(user).and_return "user_email_z"
  187. 1 expect(subject).to receive(:yaml_line).with( "out", "indent", ":user_email_z:")
  188. 1 expect(subject).to receive(:yaml_item).with( "out", "base indent", ":email:", "email z", escape: true)
  189. 1 expect(subject).to receive(:attribute_names_user).and_return ["snail mail", "email"]
  190. 1 expect(subject).to receive(:yaml_item_user).with("out", "base indent", user, name: "snail mail")
  191. 1 subject.yaml_body_user_body "out", indent_base: "base ", indent: "indent", user: user
  192. 1 subject.instance_variable_get(:@total_users_exported) == 1
  193. end
  194. end
  195. 1 describe "#yaml_body_users" do
  196. 1 before {
  197. 2 allow(subject).to receive(:yaml_line).with( "out", "indent", ':user_emails:' )
  198. }
  199. 1 context "has users" do
  200. 1 before {
  201. 1 allow(subject).to receive(:yaml_item).with( "out", "indent", ":total_user_count:", 3 )
  202. 1 allow(subject).to receive(:yaml_item).with( "out", "baseindent-", "", "email1", escape: true )
  203. 1 allow(subject).to receive(:yaml_item).with( "out", "baseindent-", "", "email2", escape: true )
  204. 1 allow(subject).to receive(:yaml_item).with( "out", "baseindent-", "", "email3", escape: true )
  205. }
  206. 1 it "calls yaml_item, yaml_line, and yaml_item again for each user" do
  207. 1 users = [OpenStruct.new(email: 'email1'), OpenStruct.new(email: 'email2'), OpenStruct.new(email: 'email3')]
  208. 1 subject.yaml_body_users "out", indent_base: "base", indent: "indent", users: users
  209. end
  210. end
  211. 1 context "has no users" do
  212. 1 before {
  213. 1 allow(subject).to receive(:yaml_item).with( "out", "indent", ":total_user_count:", 0 )
  214. }
  215. 1 it "calls yaml_item and yaml_line" do
  216. 1 subject.yaml_body_users "out", indent_base: "base", indent: "indent", users: []
  217. end
  218. end
  219. end
  220. 1 describe "#yaml_body_works" do
  221. 1 context "when result of attribute_names_work is in skip array" do
  222. 1 concern = OpenStruct.new(id: "id", admin_set_id: "admin set id", edit_users: "edit users", file_set_ids: ["id1", "id2"],
  223. total_file_size: 2, visibility: "promotional")
  224. 1 before {
  225. 2 allow(subject).to receive(:human_readable_size).with(2).and_return "a goodly number of 2"
  226. 2 allow(subject).to receive(:attribute_names_work).and_return %w[ prior_identifier rights rights_license subject subject_discipline total_file_size ]
  227. 2 allow(subject).to receive(:yaml_item).with( "out", "indent", ":id:", "id")
  228. 2 allow(subject).to receive(:yaml_item).with( "out", "indent", ":admin_set_id:", "admin set id", escape: true )
  229. 2 allow(subject).to receive(:yaml_item).with( "out", "indent", ":edit_users:", "edit users", escape: true )
  230. 2 allow(subject).to receive(:yaml_item_prior_identifier).with( "out", "indent", curation_concern: concern )
  231. 2 allow(subject).to receive(:yaml_item_rights).with( "out", "indent", curation_concern: concern )
  232. 2 allow(subject).to receive(:yaml_item_subject).with( "out", "indent", curation_concern: concern )
  233. 2 allow(subject).to receive(:yaml_item).with( "out", "indent", ":total_file_count:", 2 )
  234. 2 allow(subject).to receive(:yaml_item).with( "out", "indent", ":total_file_size:", 2 )
  235. 2 allow(subject).to receive(:yaml_item).with( "out", "indent", ":total_file_size_human_readable:", "a goodly number of 2", escape: true )
  236. 2 allow(subject).to receive(:yaml_item).with( "out", "indent", ":visibility:", "promotional")
  237. }
  238. 1 it "skips yaml_item_work" do
  239. 1 expect(subject).to receive(:yaml_item).with( "out", "indent", ":id:", "id")
  240. 1 expect(subject).to receive(:yaml_item).with( "out", "indent", ":admin_set_id:", "admin set id", escape: true )
  241. 1 expect(subject).to receive(:yaml_item).with( "out", "indent", ":edit_users:", "edit users", escape: true )
  242. 1 expect(subject).to receive(:yaml_item_prior_identifier).with( "out", "indent", curation_concern: concern )
  243. 1 expect(subject).to receive(:yaml_item_rights).with( "out", "indent", curation_concern: concern )
  244. 1 expect(subject).to receive(:yaml_item_subject).with( "out", "indent", curation_concern: concern )
  245. 1 expect(subject).to receive(:yaml_item).with( "out", "indent", ":total_file_count:", 2 )
  246. 1 expect(subject).to receive(:yaml_item).with( "out", "indent", ":total_file_size:", 2 )
  247. 1 expect(subject).to receive(:yaml_item).with( "out", "indent", ":total_file_size_human_readable:", "a goodly number of 2", escape: true )
  248. 1 expect(subject).to receive(:yaml_item).with( "out", "indent", ":visibility:", "promotional")
  249. 1 subject.yaml_body_works "out", indent: "indent", curation_concern: concern
  250. 1 subject.instance_variable_get(:@total_works_exported) == 1
  251. end
  252. 1 context "when result of attribute_names_work is not in skip array" do
  253. 1 before {
  254. 1 allow(subject).to receive(:attribute_names_work).and_return ["unidentifiable"]
  255. 1 allow(subject).to receive(:yaml_item_work).with( "out", "indent", concern, name: "unidentifiable")
  256. }
  257. 1 it "calls yaml_item_work" do
  258. 1 expect(subject).to receive(:yaml_item_work).with( "out", "indent", concern, name: "unidentifiable")
  259. 1 subject.yaml_body_works "out", indent: "indent", curation_concern: concern
  260. end
  261. end
  262. end
  263. end
  264. 1 describe "#yaml_escape_value" do
  265. 1 context "when value argument is nil" do
  266. 1 it "returns blank" do
  267. 1 expect(subject.yaml_escape_value nil).to be_blank
  268. end
  269. end
  270. 1 context "when value argument is not nil and escape is false" do
  271. 1 it "returns value argument" do
  272. 1 expect(subject.yaml_escape_value "valuable").to eq "valuable"
  273. end
  274. end
  275. 1 context "when value argument is not nil and comment and escape are true" do
  276. 1 it "returns value argument" do
  277. 1 expect(subject.yaml_escape_value "valuable", comment: true, escape: true).to eq "valuable"
  278. end
  279. end
  280. 1 context "when value argument is not nil and escape is true and comment is false" do
  281. 1 it "returns value argument as json" do
  282. 1 expect(subject.yaml_escape_value "valuable", comment: false, escape: true).to eq "\"valuable\""
  283. end
  284. end
  285. 1 context "when value argument is blank and escape is true and comment is false" do
  286. 1 it "returns blank" do
  287. 1 expect(subject.yaml_escape_value "", comment: false, escape: true).to be_blank
  288. end
  289. end
  290. end
  291. 1 describe "#yaml_export_file_path" do
  292. 1 file_set = OpenStruct.new(id: 'file set id')
  293. 1 before {
  294. 1 allow(subject).to receive(:yaml_export_file_name).with(file_set: file_set).and_return "export file name "
  295. }
  296. 1 it "returns string" do
  297. 1 expect(subject.yaml_export_file_path target_dirname: ["dirname1 ", "dirname2 "], file_set: file_set)
  298. .to eq "dirname1 file set id_export file name dirname2 "
  299. end
  300. end
  301. # NOTE: if/else in function doesn't make a difference
  302. 1 describe "#yaml_export_file_name" do
  303. 1 fileset_arg = OpenStruct.new(title: ["*file^", "set"])
  304. 1 context "when file is nil" do
  305. 1 before {
  306. 1 allow(Deepblue::MetadataHelper).to receive(:file_from_file_set).with(fileset_arg).and_return nil
  307. }
  308. 1 it "returns filename appropriate string" do
  309. 1 expect(subject.yaml_export_file_name file_set: fileset_arg).to eq "_file_"
  310. end
  311. end
  312. 1 context "when file is not nil" do
  313. 1 before {
  314. 1 allow(Deepblue::MetadataHelper).to receive(:file_from_file_set).with(fileset_arg).and_return MockFileSet.new
  315. }
  316. 1 it "returns filename appropriate string" do
  317. 1 expect(subject.yaml_export_file_name file_set: fileset_arg).to eq "_file_"
  318. end
  319. end
  320. end
  321. 1 describe "#yaml_file_set_checksum" do
  322. 1 context "when file present" do
  323. 1 before {
  324. 1 allow(Deepblue::MetadataHelper).to receive(:file_from_file_set).with("fileset").and_return OpenStruct.new(checksum: 'check sum')
  325. }
  326. 1 it "returns file.checksum" do
  327. 1 expect(subject.yaml_file_set_checksum file_set: "fileset").to eq "check sum"
  328. end
  329. end
  330. 1 context "when file not present" do
  331. 1 before {
  332. 1 allow(Deepblue::MetadataHelper).to receive(:file_from_file_set).with("fileset").and_return nil
  333. }
  334. 1 it "returns nil" do
  335. 1 expect(subject.yaml_file_set_checksum file_set: "fileset").to be_blank
  336. end
  337. end
  338. end
  339. 1 pending "#yaml_filename"
  340. 1 describe "#yaml_filename_collection" do
  341. 1 before {
  342. 1 allow(subject).to receive(:yaml_filename).with pathname_dir: "pathname", id: "ID", prefix: 'c_', task: "populate"
  343. }
  344. 1 it "calls yaml_filename" do
  345. 1 expect(subject).to receive(:yaml_filename).with pathname_dir: "pathname", id: "ID", prefix: 'c_', task: "populate"
  346. 1 subject.yaml_filename_collection pathname_dir: "pathname", collection: OpenStruct.new(id: 'ID'), task: 'populate'
  347. end
  348. end
  349. 1 describe "#yaml_filename_users" do
  350. 1 before {
  351. 1 allow(subject).to receive(:yaml_filename).with pathname_dir: "pathname", id: "", prefix: 'users', task: "populate"
  352. }
  353. 1 it "calls yaml_filename" do
  354. 1 expect(subject).to receive(:yaml_filename).with pathname_dir: "pathname", id: "", prefix: 'users', task: "populate"
  355. 1 subject.yaml_filename_users pathname_dir: "pathname", task: 'populate'
  356. end
  357. end
  358. 1 describe "#yaml_filename_work" do
  359. 1 before {
  360. 1 allow(subject).to receive(:yaml_filename).with pathname_dir: "pathname", id: "identify", prefix: 'w_', task: "populate"
  361. }
  362. 1 it "calls yaml_filename" do
  363. 1 expect(subject).to receive(:yaml_filename).with pathname_dir: "pathname", id: "identify", prefix: 'w_', task: "populate"
  364. 1 subject.yaml_filename_work pathname_dir: "pathname", work: OpenStruct.new(id: 'identify'), task: 'populate'
  365. end
  366. end
  367. 1 describe "#yaml_header" do
  368. 1 before {
  369. 1 allow(DateTime).to receive(:now).and_return DateTime.new(2025, 6, 6, 9, 10, 35)
  370. 1 allow(subject).to receive(:source).and_return "DBDv3"
  371. 1 allow(subject).to receive(:mode).and_return "modular"
  372. 1 allow(subject).to receive(:yaml_line).with "out", "indent", ':email:', "depositor"
  373. 1 allow(subject).to receive(:yaml_line).with "out", "indent", ':visibility:', "visible"
  374. 1 allow(subject).to receive(:yaml_line).with "out", "indent", ':ingester:', ''
  375. 1 allow(subject).to receive(:yaml_line).with "out", "indent", ':source:', "DBDv3"
  376. 1 allow(subject).to receive(:yaml_line).with "out", "indent", ':export_timestamp:', '2025-06-06T09:10:35+00:00'
  377. 1 allow(subject).to receive(:yaml_line).with "out", "indent", ':mode:', "modular"
  378. 1 allow(subject).to receive(:yaml_line).with "out", "indent", ':id:', "identifier"
  379. 1 allow(subject).to receive(:yaml_line).with "out", "indent", "header"
  380. }
  381. 1 it "calls yaml_line multiple times with different arguments" do
  382. 1 expect(subject).to receive(:yaml_line).with "out", "indent", ':email:', "depositor"
  383. 1 expect(subject).to receive(:yaml_line).with "out", "indent", ':visibility:', "visible"
  384. 1 expect(subject).to receive(:yaml_line).with "out", "indent", ':ingester:', ''
  385. 1 expect(subject).to receive(:yaml_line).with "out", "indent", ':source:', "DBDv3"
  386. 1 expect(subject).to receive(:yaml_line).with "out", "indent", ':export_timestamp:', '2025-06-06T09:10:35+00:00'
  387. 1 expect(subject).to receive(:yaml_line).with "out", "indent", ':mode:', "modular"
  388. 1 expect(subject).to receive(:yaml_line).with "out", "indent", ':id:', "identifier"
  389. 1 expect(subject).to receive(:yaml_line).with "out", "indent", "header"
  390. 1 concern = OpenStruct.new(depositor: 'depositor', visibility: "visible", id: "identifier")
  391. 1 subject.yaml_header "out", indent: "indent", curation_concern: concern, header_type: "header"
  392. end
  393. end
  394. 1 describe "#yaml_header_populate" do
  395. 1 before {
  396. 1 allow(subject).to receive(:yaml_line).with "out", "indent", 'target', comment: true
  397. 1 allow(subject).to receive(:yaml_line).with "out", "indent", "bundle exec rake umrdr:populate[target]", comment: true
  398. 1 allow(subject).to receive(:yaml_line).with "out", "indent", "---"
  399. 1 allow(subject).to receive(:yaml_line).with "out", "indent", ":user:"
  400. }
  401. 1 it "calls yaml_line multiple times with different arguments" do
  402. 1 expect(subject).to receive(:yaml_line).with "out", "indent", 'target', comment: true
  403. 1 expect(subject).to receive(:yaml_line).with "out", "indent", "bundle exec rake umrdr:populate[target]", comment: true
  404. 1 expect(subject).to receive(:yaml_line).with "out", "indent", "---"
  405. 1 expect(subject).to receive(:yaml_line).with "out", "indent", ":user:"
  406. 1 subject.yaml_header_populate "out", indent: "indent", target_filename: "target"
  407. end
  408. end
  409. 1 describe "#yaml_header_users" do
  410. 1 before {
  411. 1 allow(subject).to receive(:source).and_return "DBDv3"
  412. 1 allow(subject).to receive(:mode).and_return "modular"
  413. 1 allow(DateTime).to receive(:now).and_return DateTime.new(2025, 6, 6, 0, 0, 30)
  414. 1 allow(subject).to receive(:yaml_line).with "out", "indent", ':ingester:', ''
  415. 1 allow(subject).to receive(:yaml_line).with "out", "indent", ':source:', "DBDv3"
  416. 1 allow(subject).to receive(:yaml_line).with "out", "indent", ':export_timestamp:', '30'
  417. 1 allow(subject).to receive(:yaml_line).with "out", "indent", ':mode:', 'modular'
  418. 1 allow(subject).to receive(:yaml_line).with "out", "indent", ':users:'
  419. }
  420. 1 it "calls yaml_line multiple times with different arguments" do
  421. 1 expect(subject).to receive(:yaml_line).with "out", "indent", ':ingester:', ''
  422. 1 expect(subject).to receive(:yaml_line).with "out", "indent", ':source:', "DBDv3"
  423. 1 expect(subject).to receive(:yaml_line).with "out", "indent", ':export_timestamp:', '2025-06-06T00:00:30+00:00'
  424. 1 expect(subject).to receive(:yaml_line).with "out", "indent", ':mode:', 'modular'
  425. 1 expect(subject).to receive(:yaml_line).with "out", "indent", ':users:'
  426. 1 subject.yaml_header_users "out", indent: "indent"
  427. end
  428. end
  429. 1 describe "#yaml_is_a_work?" do
  430. 1 context "when source is 'DBDv2'" do
  431. 1 before {
  432. 2 allow(subject).to receive(:source).and_return "DBDv2"
  433. }
  434. 1 it "returns true when curation_concern is a DataSet" do
  435. 1 expect(subject.yaml_is_a_work? curation_concern: DataSet.new).to eq true
  436. end
  437. 1 it "returns false when curation_concern is not a DataSet" do
  438. 1 expect(subject.yaml_is_a_work? curation_concern: GenericWork.new).to eq false
  439. end
  440. end
  441. 1 context "when source is not 'DBDv2'" do
  442. 1 before {
  443. 2 allow(subject).to receive(:source).and_return "DBDv1"
  444. }
  445. 1 it "returns true when curation_concern is a GenericWork" do
  446. 1 expect(subject.yaml_is_a_work? curation_concern: GenericWork.new).to eq true
  447. end
  448. 1 it "returns false when curation_concern is not a GenericWork" do
  449. 1 expect(subject.yaml_is_a_work? curation_concern: DataSet.new).to eq false
  450. end
  451. end
  452. end
  453. 1 pending "#yaml_item"
  454. 1 describe "#yaml_item_collection" do
  455. 1 context "when ATTRIBUTE_NAMES_IGNORE includes name argument" do
  456. 1 it "returns blank" do
  457. 1 expected_attribute_names_ignore.each do |attr_name|
  458. 7 expect(subject.yaml_item_collection "out", "indent", "curation concern", name: attr_name).to be_blank
  459. end
  460. end
  461. end
  462. 1 context "when ATTRIBUTE_NAMES_IGNORE doesn't include name argument" do
  463. 1 it "calls yaml_item" do
  464. 1 expect(subject).to receive(:yaml_item).with "out", "indent", ":banana:", "yellow", escape: true
  465. 1 subject.yaml_item_collection "out", "indent", { "banana" => "yellow"}, name: "banana"
  466. end
  467. end
  468. 1 context "when value blank and name not in ATTRIBUTE_NAMES_ALWAYS_INCLUDE_CC" do
  469. 1 it "returns blank" do
  470. 1 expect(subject.yaml_item_collection "out", "indent", { "banana" => "" }, name: "banana").to be_blank
  471. end
  472. end
  473. end
  474. 1 describe "#yaml_item_file_set" do
  475. 1 context "when ATTRIBUTE_NAMES_IGNORE includes name argument" do
  476. 1 it "returns blank" do
  477. 1 expected_attribute_names_ignore.each do |attr_name|
  478. 7 expect(subject.yaml_item_file_set "out", "indent", "file set", name: attr_name).to be_blank
  479. end
  480. end
  481. end
  482. 1 context "when ATTRIBUTE_NAMES_IGNORE doesn't include name argument" do
  483. 1 it "calls yaml_item" do
  484. 1 expect(subject).to receive(:yaml_item).with "out", "indent", ":apple:", "red", escape: true
  485. 1 subject.yaml_item_file_set "out", "indent", { "apple" => "red"}, name: "apple"
  486. end
  487. end
  488. 1 context "when value blank and name not in ATTRIBUTE_NAMES_ALWAYS_INCLUDE_FILE_SET" do
  489. 1 it "returns blank" do
  490. 1 expect(subject.yaml_item_file_set "out", "indent", { "apple" => "" }, name: "apple").to be_blank
  491. end
  492. end
  493. end
  494. 1 describe "#yaml_item_prior_identifier" do
  495. 1 context "when source is 'DBDv1'" do
  496. 1 before {
  497. 1 allow(subject).to receive(:source).and_return "DBDv1"
  498. }
  499. 1 it "calls yaml_item without curation_concern.prior_identifier" do
  500. 1 expect(subject).to receive(:yaml_item).with "out", "indent", ":prior_identifier:", ""
  501. 1 subject.yaml_item_prior_identifier "out", "indent", curation_concern: "concern"
  502. end
  503. end
  504. 1 context "when source is not 'DBDv1'" do
  505. 1 before {
  506. 1 allow(subject).to receive(:source).and_return "DBDv2"
  507. }
  508. 1 it "calls yaml_item with curation_concern.prior_identifier" do
  509. 1 expect(subject).to receive(:yaml_item).with "out", "indent", ":prior_identifier:", "concern identifier"
  510. 1 subject.yaml_item_prior_identifier "out", "indent", curation_concern: OpenStruct.new(prior_identifier: 'concern identifier')
  511. end
  512. end
  513. end
  514. 1 describe "#yaml_item_referenced_by" do
  515. 1 context "when source is 'DBDv1'" do
  516. 1 before {
  517. 1 allow(subject).to receive(:source).and_return "DBDv1"
  518. }
  519. 1 it "calls yaml_item with subject" do
  520. 1 expect(subject).to receive(:yaml_item).with "out", "indent", ":isReferencedBy:", "reference concern", escape: true
  521. 1 subject.yaml_item_referenced_by "out", "indent", curation_concern: OpenStruct.new(isReferencedBy: 'reference concern')
  522. end
  523. end
  524. 1 context "when source is not 'DBDv1'" do
  525. 1 before {
  526. 1 allow(subject).to receive(:source).and_return "DBDv2"
  527. }
  528. 1 it "calls yaml_item with subject_discipline" do
  529. 1 expect(subject).to receive(:yaml_item).with "out", "indent", ":referenced_by:", "referral concern", escape: true
  530. 1 subject.yaml_item_referenced_by "out", "indent", curation_concern: OpenStruct.new(referenced_by: 'referral concern')
  531. end
  532. end
  533. end
  534. 1 describe "#yaml_item_rights" do
  535. 1 context "when source is 'DBDv1'" do
  536. 1 before {
  537. 1 allow(subject).to receive(:source).and_return "DBDv1"
  538. }
  539. 1 it "calls yaml_item with subject" do
  540. 1 expect(subject).to receive(:yaml_item).with "out", "indent", ":rights:", "rights concern", escape: true
  541. 1 subject.yaml_item_rights "out", "indent", curation_concern: OpenStruct.new(rights: 'rights concern')
  542. end
  543. end
  544. 1 context "when source is not 'DBDv1'" do
  545. 1 before {
  546. 1 allow(subject).to receive(:source).and_return "DBDv2"
  547. }
  548. 1 it "calls yaml_item with subject_discipline" do
  549. 1 expect(subject).to receive(:yaml_item).with "out", "indent", ":rights_license:", "license", escape: true
  550. 1 subject.yaml_item_rights "out", "indent", curation_concern: OpenStruct.new(rights_license: 'license')
  551. end
  552. end
  553. end
  554. 1 describe "#yaml_item_subject" do
  555. 1 context "when source is 'DBDv1'" do
  556. 1 before {
  557. 1 allow(subject).to receive(:source).and_return "DBDv1"
  558. }
  559. 1 it "calls yaml_item with subject" do
  560. 1 expect(subject).to receive(:yaml_item).with "out", "indent", ":subject:", "subject concern", escape: true
  561. 1 subject.yaml_item_subject "out", "indent", curation_concern: OpenStruct.new(subject: 'subject concern')
  562. end
  563. end
  564. 1 context "when source is not 'DBDv1'" do
  565. 1 before {
  566. 1 allow(subject).to receive(:source).and_return "DBDv2"
  567. }
  568. 1 it "calls yaml_item with subject_discipline" do
  569. 1 expect(subject).to receive(:yaml_item).with "out", "indent", ":subject_discipline:", "discipline", escape: true
  570. 1 subject.yaml_item_subject "out", "indent", curation_concern: OpenStruct.new(subject_discipline: 'discipline')
  571. end
  572. end
  573. end
  574. 1 describe "#yaml_item_user" do
  575. 1 context "when ATTRIBUTE_NAMES_USER_IGNORE includes name argument" do
  576. 1 it "returns blank" do
  577. 1 expected_attribute_names_user_ignore.each do |attr_name|
  578. 4 expect(subject.yaml_item_user "out", "indent", "user", name: attr_name).to be_blank
  579. end
  580. end
  581. end
  582. 1 context "when ATTRIBUTE_NAMES_USER_IGNORE doesn't include name argument" do
  583. 1 it "calls yaml_item" do
  584. 1 expect(subject).to receive(:yaml_item).with "out", "indent", ":frosting:", "cream cheese", escape: true
  585. 1 subject.yaml_item_user "out", "indent", { "frosting" => "cream cheese"}, name: "frosting"
  586. end
  587. end
  588. 1 context "when value blank and name not in ATTRIBUTE_NAMES_ALWAYS_INCLUDE_USER" do
  589. 1 it "returns blank" do
  590. 1 expect(subject.yaml_item_user "out", "indent", { "frosting" => "" }, name: "frosting").to be_blank
  591. end
  592. end
  593. end
  594. 1 describe "#yaml_item_work" do
  595. 1 context "when ATTRIBUTE_NAMES_IGNORE includes name argument" do
  596. 1 it "returns blank" do
  597. 1 expected_attribute_names_ignore.each do |attr_name|
  598. 7 expect(subject.yaml_item_work "out", "indent", "curation concern", name: attr_name).to be_blank
  599. end
  600. end
  601. end
  602. 1 context "when ATTRIBUTE_NAMES_IGNORE doesn't include name argument" do
  603. 1 it "calls yaml_item" do
  604. 1 expect(subject).to receive(:yaml_item).with "out", "indent", ":cake:", "chocolate", escape: true
  605. 1 subject.yaml_item_work "out", "indent", { "cake" => "chocolate" }, name: "cake"
  606. end
  607. end
  608. 1 context "when value blank and name not in ATTRIBUTE_NAMES_ALWAYS_INCLUDE_CC" do
  609. 1 it "returns blank" do
  610. 1 expect(subject.yaml_item_work "out", "indent", { "cake" => "" }, name: "cake").to be_blank
  611. end
  612. end
  613. end
  614. 1 describe "#yaml_line" do
  615. 1 context "when comment is false" do
  616. 1 before {
  617. 1 allow(subject).to receive(:yaml_escape_value).with('', comment: false, escape: false).and_return "yaml escape value"
  618. }
  619. 1 it "outputs text" do
  620. 1 out_object = MockOutput.new
  621. 1 expect(out_object).to receive(:puts).with("indent label yaml escape value")
  622. 1 subject.yaml_line out_object, "indent ", "label", comment: false
  623. end
  624. end
  625. 1 context "when comment is true" do
  626. 1 before {
  627. 1 allow(subject).to receive(:yaml_escape_value).with('', comment: true, escape: false).and_return "comment"
  628. }
  629. 1 it "outputs text with preceding hashtag" do
  630. 1 out_object = MockOutput.new
  631. 1 expect(out_object).to receive(:puts).with("# indent label comment")
  632. 1 subject.yaml_line out_object, "indent ", "label", comment: true
  633. end
  634. end
  635. end
  636. 1 describe "#yaml_populate_collection" do
  637. 1 object1 = OpenStruct.new(id: 111)
  638. 1 object2 = OpenStruct.new(id: 222)
  639. 1 concern_objects = OpenStruct.new(member_objects: [object1, object2])
  640. 1 concern_empty = OpenStruct.new(member_objects: [])
  641. 1 context "when out argument is not nil" do
  642. 1 before {
  643. 3 allow(subject).to receive(:log_provenance_migrate).with( curation_concern: concern_objects )
  644. 3 allow(subject).to receive(:yaml_header_populate).with( "outboard", indent: "", target_filename: "filename" )
  645. 3 allow(subject).to receive(:yaml_header).with( "outboard", indent: " ", curation_concern: concern_objects,
  646. header_type: ':collections:')
  647. 3 allow(subject).to receive(:yaml_body_collections).with( "outboard", indent: " ", curation_concern: concern_objects)
  648. }
  649. 1 context "when populate_works is false" do
  650. 1 before {
  651. 1 allow(subject).to receive(:mode).and_return "work"
  652. }
  653. 1 it "calls various methods" do
  654. 1 expect(subject).not_to receive(:log_provenance_migrate)
  655. 1 expect(subject).to receive(:yaml_header_populate).with( "outboard", indent: "", target_filename: "filename" )
  656. 1 expect(subject).to receive(:yaml_header).with( "outboard", indent: " ", curation_concern: concern_objects,
  657. header_type: ':collections:')
  658. 1 expect(subject).to receive(:yaml_body_collections).with( "outboard", indent: " ", curation_concern: concern_objects)
  659. 1 subject.yaml_populate_collection collection: concern_objects, out: "outboard", populate_works: false, target_filename: "filename"
  660. end
  661. end
  662. 1 context "when populate_works is true and collection.member_objects has no values" do
  663. 1 before {
  664. 1 allow(subject).to receive(:mode).and_return "work"
  665. 1 allow(subject).to receive(:log_provenance_migrate).with( curation_concern: concern_empty )
  666. 1 allow(subject).to receive(:yaml_header).with( "outboard", indent: " ", curation_concern: concern_empty,
  667. header_type: ':collections:')
  668. 1 allow(subject).to receive(:yaml_body_collections).with( "outboard", indent: " ", curation_concern: concern_empty)
  669. }
  670. 1 it "calls various methods" do
  671. 1 expect(subject).not_to receive(:log_provenance_migrate)
  672. 1 expect(subject).to receive(:yaml_header_populate).with( "outboard", indent: "", target_filename: "filename" )
  673. 1 expect(subject).to receive(:yaml_header).with( "outboard", indent: " ", curation_concern: concern_empty,
  674. header_type: ':collections:')
  675. 1 expect(subject).to receive(:yaml_body_collections).with( "outboard", indent: " ", curation_concern: concern_empty)
  676. 1 subject.yaml_populate_collection collection: concern_empty, out: "outboard", populate_works: true, target_filename: "filename"
  677. end
  678. end
  679. 1 context "when populate_works is true and collection.member_objects has value(s) and mode is MetadataHelper::MODE_MIGRATE" do
  680. 1 before {
  681. 1 allow(subject).to receive(:mode).and_return "migrate"
  682. 1 allow(subject).to receive(:yaml_line).with( "outboard", " ", ':works:' )
  683. 1 allow(subject).to receive(:yaml_is_a_work?).with( curation_concern: object1 ).and_return true
  684. 1 allow(subject).to receive(:yaml_is_a_work?).with( curation_concern: object2 ).and_return false
  685. 1 allow(subject).to receive(:yaml_item).with( "outboard", " -", '', 111, escape: true )
  686. 1 allow(subject).to receive(:yaml_line).with( "outboard", " ", ":works_111:" )
  687. 1 allow(subject).to receive(:log_provenance_migrate).with( curation_concern: object1, parent: concern_objects )
  688. 1 allow(subject).to receive(:yaml_body_works).with( "outboard", indent: " ", curation_concern: object1 )
  689. 1 allow(subject).to receive(:yaml_body_files).with( "outboard", indent_base: " ", indent: " ",
  690. curation_concern: object1, target_dirname: "directoryname")
  691. }
  692. 1 it "calls various methods" do
  693. 1 expect(subject).to receive(:log_provenance_migrate).with( curation_concern: concern_objects )
  694. 1 expect(subject).to receive(:yaml_header_populate).with( "outboard", indent: "", target_filename: "filename" )
  695. 1 expect(subject).to receive(:yaml_header).with( "outboard", indent: " ", curation_concern: concern_objects,
  696. header_type: ':collections:')
  697. 1 expect(subject).to receive(:yaml_body_collections).with( "outboard", indent: " ", curation_concern: concern_objects)
  698. # expect(subject).to receive(:yaml_line).with( "outboard", " ", ':works:' )
  699. 1 expect(subject).to receive(:yaml_item).with( "outboard", " -", '', 111, escape: true )
  700. 1 expect(subject).not_to receive(:yaml_item).with( "outboard", " -", '', 222, escape: true )
  701. 1 expect(subject).to receive(:yaml_line).with( "outboard", " ", ":works_111:" )
  702. 1 expect(subject).not_to receive(:yaml_line).with( "outboard", " ", ":works_222:" )
  703. 1 expect(subject).to receive(:log_provenance_migrate).with( curation_concern: object1, parent: concern_objects )
  704. 1 expect(subject).not_to receive(:log_provenance_migrate).with( curation_concern: object2, parent: concern_objects )
  705. 1 expect(subject).to receive(:yaml_body_works).with( "outboard", indent: " ", curation_concern: object1 )
  706. # expect(subject).to receive(:yaml_body_files).with( "outboard", indent_base: " ", indent: " ",
  707. # curation_concern: object1, target_dirname: "directoryname")
  708. 1 expect(subject).not_to receive(:yaml_body_works).with( "outboard", indent: " ", curation_concern: object2 )
  709. 1 expect(subject).not_to receive(:yaml_body_files).with( "outboard", indent_base: " ", indent: " ",
  710. curation_concern: object2, target_dirname: "directoryname")
  711. 1 subject.yaml_populate_collection collection: concern_objects, out: "outboard", populate_works: true, target_filename: "filename",
  712. target_dirname: "directoryname"
  713. end
  714. end
  715. end
  716. 1 context "when out argument is nil" do
  717. 1 skip "Add tests"
  718. end
  719. end
  720. 1 describe "#yaml_populate_stats" do
  721. 1 before {
  722. 1 allow(subject).to receive(:human_readable_size).with(0).and_return 100
  723. }
  724. 1 it "returns Hash" do
  725. 1 expected_hash = {:total_collections_exported => 0,
  726. :total_works_exported => 0,
  727. :total_file_sets_exported => 0,
  728. :total_file_sets_size_exported => 0,
  729. :total_file_sets_size_readable_exported => 100,
  730. :total_users_exported => 0 }
  731. 1 expect(subject.yaml_populate_stats).to eq expected_hash
  732. end
  733. end
  734. 1 describe "#yaml_populate_users" do
  735. 1 context "when out argument is not nil" do
  736. 1 before {
  737. 1 allow(Dir).to receive(:mkdir).with(anything)
  738. 1 allow(subject).to receive(:yaml_header_populate).with( "outside", indent: "", rake_task: 'umrdr:populate_users', target_filename: "filename" )
  739. 1 allow(subject).to receive(:yaml_header_users).with( "outside", indent: " ")
  740. 1 allow(User).to receive(:all).and_return ["user1"]
  741. 1 allow(subject).to receive(:yaml_body_users).with( "outside",
  742. indent_base: " ",
  743. indent: " ",
  744. users: ["user1"])
  745. 1 allow(subject).to receive(:yaml_body_user_body).with( "outside",
  746. indent_base: " ",
  747. indent: " ",
  748. user:"user1")
  749. }
  750. 1 it "returns nil" do
  751. 1 expect(subject).to receive(:yaml_header_populate).with( "outside", indent: "", rake_task: 'umrdr:populate_users', target_filename: "filename" )
  752. 1 expect(subject).to receive(:yaml_header_users).with( "outside", indent: " ")
  753. 1 expect(subject).to receive(:yaml_body_users).with( "outside",
  754. indent_base: " ",
  755. indent: " ",
  756. users: ["user1"])
  757. 1 expect(subject).to receive(:yaml_body_user_body).with( "outside",
  758. indent_base: " ",
  759. indent: " ",
  760. user:"user1")
  761. 1 expect(subject.yaml_populate_users out: "outside", target_filename: "filename").to be_blank
  762. end
  763. end
  764. 1 context "when out argument is nil" do
  765. 1 skip "Add tests"
  766. end
  767. end
  768. 1 describe "#yaml_populate_work" do
  769. 1 context "when out argument is not nil" do
  770. 1 before {
  771. 2 allow(subject).to receive(:log_provenance_migrate).with( curation_concern: "concern" )
  772. 2 allow(subject).to receive(:yaml_header_populate).with( "I'm going out", indent: "", target_filename: "filename" )
  773. 2 allow(subject).to receive(:yaml_header).with( "I'm going out",
  774. indent: " ",
  775. curation_concern: "concern",
  776. header_type: ':works:' )
  777. 2 allow(subject).to receive(:yaml_body_works).with( "I'm going out", indent: " ", curation_concern: "concern" )
  778. 2 allow(subject).to receive(:yaml_body_files).with( "I'm going out",
  779. indent_base: " ",
  780. indent: " ",
  781. curation_concern: "concern",
  782. target_dirname: "dirname" )
  783. }
  784. 1 context "when mode is MetadataHelper::MODE_MIGRATE" do
  785. 1 before {
  786. 1 allow(subject).to receive(:mode).and_return "migrate"
  787. }
  788. 1 it 'calls log_provenance_migrate, other functions and returns nil' do
  789. 1 expect(subject).to receive(:log_provenance_migrate).with( curation_concern: "concern" )
  790. 1 expect(subject).to receive(:yaml_header_populate).with( "I'm going out", indent: "", target_filename: "filename" )
  791. 1 expect(subject).to receive(:yaml_header).with( "I'm going out",
  792. indent: " ",
  793. curation_concern: "concern",
  794. header_type: ':works:' )
  795. 1 expect(subject).to receive(:yaml_body_works).with( "I'm going out", indent: " ", curation_concern: "concern" )
  796. 1 expect(subject).to receive(:yaml_body_files).with( "I'm going out",
  797. indent_base: " ",
  798. indent: " ",
  799. curation_concern: "concern",
  800. target_dirname: "dirname" )
  801. 1 expect(subject.yaml_populate_work(curation_concern: "concern", out: "I'm going out", target_filename: "filename",
  802. target_dirname: "dirname")).to be_blank
  803. end
  804. end
  805. 1 context "when mode is not MetadataHelper::MODE_MIGRATE" do
  806. 1 before {
  807. 1 allow(subject).to receive(:mode).and_return "work"
  808. }
  809. 1 it 'does not call log_provenance_migrate, calls various functions and returns nil' do
  810. 1 expect(subject).not_to receive(:log_provenance_migrate)
  811. 1 expect(subject).to receive(:yaml_header_populate).with( "I'm going out", indent: "", target_filename: "filename" )
  812. 1 expect(subject).to receive(:yaml_header).with( "I'm going out",
  813. indent: " ",
  814. curation_concern: "concern",
  815. header_type: ':works:' )
  816. 1 expect(subject).to receive(:yaml_body_works).with( "I'm going out", indent: " ", curation_concern: "concern" )
  817. 1 expect(subject).to receive(:yaml_body_files).with( "I'm going out",
  818. indent_base: " ",
  819. indent: " ",
  820. curation_concern: "concern",
  821. target_dirname: "dirname" )
  822. 1 expect(subject.yaml_populate_work(curation_concern: "concern", out: "I'm going out", target_filename: "filename",
  823. target_dirname: "dirname")).to be_blank
  824. end
  825. end
  826. end
  827. 1 context "when out argument is nil" do
  828. 1 skip "Add tests"
  829. end
  830. end
  831. 1 describe "#yaml_targetdir" do
  832. 1 context "when called with an object that is not a Pathname" do
  833. 1 it "creates a new Pathname and returns text" do
  834. 1 skip "Add a test"
  835. end
  836. end
  837. 1 context "when called with a Pathname" do
  838. 1 it "returns text" do
  839. 1 skip "Add a test"
  840. end
  841. end
  842. end
  843. 1 describe "#yaml_targetdir_collection" do
  844. 1 before {
  845. 1 allow(subject).to receive(:yaml_targetdir).with(pathname_dir: "pathname dir", id: "collection id", prefix: "c_", task: "populate")
  846. .and_return "population"
  847. }
  848. 1 it "calls yaml_targetdir" do
  849. 1 expect(subject.yaml_targetdir_collection pathname_dir: "pathname dir", collection: OpenStruct.new(id: 'collection id')).to eq "population"
  850. end
  851. end
  852. 1 describe "#yaml_targetdir_users" do
  853. 1 before {
  854. 1 allow(subject).to receive(:yaml_targetdir).with(pathname_dir: "pathname dir", id: "", prefix: "users", task: "populate")
  855. .and_return "population"
  856. }
  857. 1 it "calls yaml_targetdir" do
  858. 1 expect(subject.yaml_targetdir_users pathname_dir: "pathname dir").to eq "population"
  859. end
  860. end
  861. 1 describe "#yaml_targetdir_work" do
  862. 1 before {
  863. 1 allow(subject).to receive(:yaml_targetdir).with(pathname_dir: "pathname dir", id: "work id", prefix: "w_", task: "populate")
  864. .and_return "yaml targetdir"
  865. }
  866. 1 it "calls yaml_targetdir" do
  867. 1 expect(subject.yaml_targetdir_work pathname_dir: "pathname dir", work: OpenStruct.new(id: 'work id')).to eq "yaml targetdir"
  868. end
  869. end
  870. 1 describe "#yaml_user_email" do
  871. 1 it "returns string" do
  872. 1 expect(subject.yaml_user_email OpenStruct.new(email: "bpotter@example.com")).to eq "user_bpotter@example.com"
  873. end
  874. end
  875. 1 describe "#yaml_work_export_files" do
  876. 1 exception = StandardError.new("error message")
  877. 1 exception.set_backtrace("backtrace")
  878. 1 context "when error occurs" do
  879. 1 before {
  880. 1 allow(subject).to receive(:open).with("dirname", "w").and_raise( exception )
  881. 1 allow(subject).to receive(:puts).with "StandardError: error message at backtrace"
  882. }
  883. 1 it "catch error" do
  884. 1 expect(subject).to receive(:open).with("dirname", "w").and_raise( exception )
  885. 1 expect(subject).to receive(:puts).with "StandardError: error message at backtrace"
  886. 1 subject.yaml_work_export_files(work: "work", target_dirname: ["dirname"], log_filename: nil)
  887. end
  888. end
  889. 1 context "when error does not occur" do
  890. 1 skip "Add tests"
  891. end
  892. end
  893. 1 describe "#yaml_work_find" do
  894. 1 context "when source is 'DBDv2'" do
  895. 1 before {
  896. 1 allow(DataSet).to receive(:find).and_return "DataSet find"
  897. }
  898. 1 it "calls DataSet.find" do
  899. 1 expect(subject.yaml_work_find curation_concern: "concern").to eq "DataSet find"
  900. end
  901. end
  902. 1 context "when source is not 'DBDv2'" do
  903. 1 before {
  904. 1 allow(subject).to receive(:source).and_return "DBDv1"
  905. 1 allow(GenericWork).to receive(:find).and_return "GenericWork find"
  906. }
  907. 1 it "calls GenericWork.find" do
  908. 1 expect(subject.yaml_work_find curation_concern: "concern").to eq "GenericWork find"
  909. end
  910. end
  911. end
  912. 1 pending "#self.init_attribute_names_always_include_cc"
  913. end

spec/support/factory_bot.rb

100.0% lines covered

2 relevant lines. 2 lines covered and 0 lines missed.
    
  1. 1 RSpec.configure do |config|
  2. 1 config.include FactoryBot::Syntax::Methods
  3. end

spec/support/factory_helpers.rb

80.0% lines covered

5 relevant lines. 4 lines covered and 1 lines missed.
    
  1. 1 module Hyrax
  2. 1 module FactoryHelpers
  3. 1 module_function
  4. 1 def mock_file_factory(opts = {})
  5. mock_model('MockOriginal',
  6. mime_type: opts.fetch(:mime_type, 'text/plain'),
  7. content: opts.fetch(:content, 'content'),
  8. file_size: opts.fetch(:file_size, []),
  9. format_label: opts.fetch(:format_label, []),
  10. height: opts.fetch(:height, []),
  11. width: opts.fetch(:width, []),
  12. filename: opts.fetch(:filename, []),
  13. well_formed: opts.fetch(:well_formed, []),
  14. page_count: opts.fetch(:page_count, []),
  15. file_title: opts.fetch(:file_title, []),
  16. last_modified: opts.fetch(:last_modified, []),
  17. original_checksum: opts.fetch(:original_checksum, []),
  18. digest: opts.fetch(:digest, []),
  19. duration: opts.fetch(:duration, []),
  20. sample_rate: opts.fetch(:sample_rate, []))
  21. end
  22. end
  23. end

spec/views/_user_util_links.html.erb_spec.rb

100.0% lines covered

12 relevant lines. 12 lines covered and 0 lines missed.
    
  1. 1 RSpec.describe '/_user_util_links.html.erb', type: :view do
  2. 1 before do
  3. 2 allow(view).to receive(:user_signed_in?).and_return(false)
  4. 2 allow(view).to receive(:current_user).and_return(nil)
  5. end
  6. 1 it 'IU Login should go to CAS' do
  7. 1 Rails.configuration.authentication_method = "iu"
  8. 1 render
  9. 1 expect(rendered).to have_link "IU Login"
  10. end
  11. 1 it 'Other login should go to regular login' do
  12. 1 Rails.configuration.authentication_method = "umich"
  13. 1 render
  14. 1 expect(rendered).to have_link 'Login'
  15. end
  16. end